2015-05-22 36 views
6

Ich arbeite mit einer MongoDB-Datenbank. Ich weiß, wenn Sie eine DateTime in Mongo einfügen, konvertiert es es in UTC. Aber ich mache einen Komponententest und meine Assert versagt.DateTime ToLocalTime schlägt fehl

[TestMethod] 
public void MongoDateConversion() { 
    DateTime beforeInsert = DateTime.Now; 
    DateTime afterInsert; 

    Car entity = new Car { 
     Name = "Putt putt", 
     LastTimestamp = beforeInsert 
    }; 

    // insert 'entity' 
    // update 'entity' from the database 

    afterInsert = entity.LastTimestamp.ToLocalTime(); 

    Assert.AreEqual(beforeInsert, afterInsert); // fails here 
} 

Ich muss etwas offensichtlich fehlen. Als ich im Debugger sehen, kann ich sehen, dass das Spiel des Datetime, aber die Assertion immer noch sagt, dass sie dies nicht tun (aber sie tun):

Result Message: Assert.AreEqual failed. Expected:<5/21/2015 8:27:04 PM>. Actual:<5/21/2015 8:27:04 PM>. 

Irgendwelche Ideen, was ich falsch hier?

EDIT:

ich mit zwei möglichen Lösungen habe kommen, von denen beide mir verlangen zu erinnern, etwas zu tun (die auf nicht immer das Beste ist, verlassen ...):

eine davon ist eine Erweiterungsmethode zu verwenden, jede Datetime aus der Datenbank kommen trunkieren:

public static DateTime Truncate(this DateTime dateTime) { 
    var timeSpan = TimeSpan.FromMilliseconds(1); 
    var ticks = -(dateTime.Ticks % timeSpan.Ticks); 
    return dateTime.AddTicks(ticks); 
} 

die anderen, nach http://alexmg.com/datetime-precision-with-mongodb-and-the-c-driver/ liest, ist jede Datetime in der POCO-Klasse zu markieren:

public class Car : IEntity { 
    public Guid Id { get; set; } 

    [BsonDateTimeOptions(Representation = BsonType.Document)] 
    public DateTime LastTimestamp { get; set; } 
} 
+0

diesem Artikel MongoDB Datumzeit Präzision zu erklären: http: // alexmg.com/datetime-precision-with-mongodb-und-der-c-driver/ –

Antwort

1

MongoDB speichert DateTimes als 64-Bit-Anzahl von Millisekunden seit der UNIX-Epoche. Siehe diese Seite: http://alexmg.com/datetime-precision-with-mongodb-and-the-c-driver/

Da die Auflösung von .NET's DateTime 100 Nanosekunden beträgt, ist MongoDB fast sicher, jede DateTime-Zeit, die Sie so durchlaufen, abzuschneiden.

Sie haben ein paar Optionen.

Option 1: Stellen Sie sicher, Lasttimestamp kürzen, wenn Sie es einrichten, oder bevor Sie den Datensatz einfügen:

long excessTicks = timestamp.Ticks % 10000; 

timestamp= new DateTime(
    ticks: timestamp.Ticks - excessTicks, 
    kind: timestamp.Kind 
); 

Dieser Ansatz fehleranfällig sein wird. Jeder, der LastTimestamp festlegt, muss daran denken, ihn zu kürzen, oder Sie können den Wert direkt vor dem Einfügen des Datensatzes abschneiden, aber möglicherweise müssen Sie das CLR-Objekt unerwartet ändern.

Alternativ könnten Sie einen Getter/Setter verwenden und LastTimestamp einfach bei jeder Einstellung auf Millisekunden abschneiden. Aber das könnte dazu führen, dass ein anderer Komponententest weiter oben auf der Leitung aus genau dem gleichen Grund versagt, wie dieser Test fehlschlägt.

Option 2: Wenn Sub-Millisekunden-Genauigkeit ist nicht wichtig, nur eine gewisse Toleranz in Ihre Behauptung setzen:

TimeSpan delta = beforeInsert - afterInsert; 

Assert.IsTrue(Math.Abs(delta.TotalMilliseconds) <= 2); 
+0

Anstelle von 'Math.Abs' können Sie auch' Assert.IsTrue (delta.Duration(). TotalMilliseconds <= 2); 'Die [' Duration() '] (https://msdn.microsoft.com/en -us/library/system.timespan.duration (v = vs.110) .aspx) gibt den absoluten Wert der Zeitspanne zurück. –

1

Ich schätze, Sie haben einen Unterschied in den Millisekunden. Versuchen Sie, die Millisekunde wie folgt Kürzen:

DateTime d = DateTime.Now; 
d = d.AddMilliseconds(-d.Millisecond); 
+0

Dies wird nicht funktionieren. DateTime.Millisecond ist eine Ganzzahl. Es gibt Ihnen nur den Millisekunden-Teil des DateTime-Werts. Es liegt immer im Bereich von 0 bis 999 pro [MSDN-Eintrag] (https://msdn.microsoft.com/en-us/library/system.datetime.millisecond.aspx). – Daryl

1

Ihr Test ist falsch (oder inkonsistent), da wird es immer ein paar Millisekunden Differenz vor und nach dem Einsatz sein. Sie könnten einfach die Datetime in eine Zeichenfolge mit dem Format dd/mm/yy hh:mm:ss konvertieren und vor und nach

vergleichen