2009-03-04 4 views
6

Ich habe zwei Datumsangaben, eine aus einem Zeitstempel und eine andere erzeuge ich in Code. Ich muss ihre Gleichheit testen und würde es gerne ohne zu viele Ausdrücke machen. Hier ist ein Beispiel für meine zwei Daten:Was ist der beste Weg, um die Gleichheit von zwei DateTime in C# zu vergleichen ... aber nur mit einer gewissen Genauigkeit?

DateTime expireTimeStampUTC = 
    DateTime.Parse(UTCValueFromDatabase)); 
DateTime expectedExpireTime = 
    DateTime.UtcNow.AddHours(NumberOfExpectedHoursInConfig); 

Das ist zu hohe Genauigkeit eines Tests:

if (expireTimeStampUTC.Equals (expectedExpireTime)) {}

ist mir egal, wenn sie sind genau in der Sekunde, nur die Stunde.

Könnte es möglicherweise die beste Lösung sein, etwas Verbindung wie dies zu tun:

if (expireTimeStampUTC.Date.Equals(expectedExpireTime.Date)) 
{ 
    if (!expireTimeStampUTC.Hour.Equals(expectedExpireTime.Hour)) 
    { 
     pass = false; 
    } 
} 

ich die meisten nicht mit C# erlebt ... gibt es einige elegent Weg, dies zu tun?

Antwort

10

Wenn das Problem, das Sie haben, weil sie ein Datenbanktyp ist, könnten Sie zu diesem Typ konvertieren und dort vergleichen, verlieren/gewinnen wir etwa eine Millisekunde Konvertierung in SQLDateTimes auf etwa 1/3 von DB speichert.

Wenn nicht, zu vergleichen, das Gerät Sie wirklich interessieren:

DateTime dt1 = DateTime.UtcNow; 
DateTime dt2 = DateTime.UtcNow.AddMinutes(59); // or 1 or 61 for test values; 

// if the dates are in the same hour (12:10 == 12:50, 1:58 != 2:02) 
if(dt1.Hour == dt2.Hour) // result 

oder wenn Sie darauf, dass sie innerhalb einer Stunde Zeitspanne sind

// if the dates are within one hour of each other (1:58 == 2:02, 3:30 != 4:45) 
if((dt1 - dt2).Duration() < TimeSpan.FromHours(1)) // result 

Hier Daten erzeugt eine Zeitspanne subtrahiert, die duration ist der 'absolute Wert' und wir erstellen das Limit explizit aus einer Einheit, die uns interessiert (FromHours) und vergleicht.

Die letzte Zeile ist so sauber, wie ich denken kann, um Gleichheit innerhalb einer bestimmten Zeitspanne zu tun.

+0

Eigentlich denke ich, das ist eigentlich besser Stil. Ich denke, es ist klarer, was passiert. Ich habe das "richtige Antwort" -Token vorher nie geändert, aber ich denke in diesem Fall ist dies die bessere Lösung. – danieltalsky

+0

Fair genug. Ich denke, es ist sechs eins/ein halbes Dutzend das andere. Die "Duration()" - Syntax ist möglicherweise besser lesbar, hat aber den (zugegebenermaßen vernachlässigbaren) Aufwand, eine TimeSpan auf beiden Seiten des Vergleichs neu zu erstellen. –

1

Konstruieren Sie neue DateTime-Objekte und vergleichen Sie sie. In C# gibt es sehr wenig Strafe für die Konstruktion von "wegwerfbaren" Objekten auf diese Weise.

+0

Wieder würde ich gerne ein Beispiel im Code sehen. – danieltalsky

6

Wie wäre es, den Unterschied zwischen den zwei Stunden zu finden und zu sehen, ob es unter einer bestimmten Schwelle liegt (sagen wir 3600 Sekunden für eine Stunde)?

var diff = expireTimeStamp.Subtract(expectedExpireTime).TotalSeconds; 
pass = Math.Abs(diff) < 3600; 
+0

Hervorragend ... das war die Antwort, die so dummerweise offensichtlich war, dass ich mich selbst dafür trete, dass ich nicht daran dachte. Vielen Dank. Und mit einem Codebeispiel auch. Magisch. – danieltalsky

+0

Obwohl kein "var" in C#;) – danieltalsky

+1

Vielleicht nicht in * Ihrem * C#! Zeit für ein Upgrade auf Visual Studio 2008, Mate! :) –

4

Subtrahieren Sie sie. Überprüfen Sie, ob der resultierende TimeSpan innerhalb einer bestimmten maximalen Reichweite ist.

+0

DateTime Werte unterstützen die Subtraktion Operation. Sie erhalten eine TimeSpan, überprüfen Sie, ob es kleiner als das angegebene Intervall ist. – Cheeso

+1

Das ist ziemlich genau das, was ich gerade gesagt habe. – recursive

1

Ich habe das Problem beim Schreiben von Komponententests festgestellt, die dann abgerufene Geschäftsobjekte festgeschrieben haben. Ich habe versucht, die "StartTime" -Eigenschaft meines Objekts zu verwenden, um sicherzustellen, dass das Objekt abgerufen werden konnte und dieses Problem festgestellt wurde. Der "StartTime" -Wert, der in der Datenbank festgeschrieben wurde, verlor 6 Stellen Genauigkeit in dem Tick-Wert!

Hier ist, wie ich meine Testbedingung so umschrieb, damit mein Test korrekt ausgeführt werden und bestanden werden würde. Relevante Zeile ist die vorletzte Zeile des Blocks.

DateTime start = DateTime.Now; 
NewEventInfo testEvent1 = FakeEvent("test01action", start); //plus other params for testing 
mServiceClient.AddEvent(testEvent1); 

EventInfo[] eventInfos = null; //code to get back events within time window 

Assert.IsNotEmpty(eventInfos); 
Assert.GreaterOrEqual(eventInfos.Length, 1); 

EventInfo resultEvent1 = eventInfos.FirstOrDefault(e => 
e.Action == "test01action" && 
Math.Abs(e.StartTime.Subtract(testEvent1.StartTime).TotalMilliseconds) < 1000); //checks dates are within 1 sec 
Assert.IsNotNull(resultEvent1); 

So kann ich das einen das Objekt sicher sein konnte, durch das Gerät zu testen, wie die EventInfo.StartTime Eigenschaft nur Datum mal mit einer Genauigkeit von 1 Sekunde verwendet begangen wurde.

EDIT: Math.Abs ​​(um DateTime Diff) hinzugefügt, um sicherzustellen, dass der absolute Wert mit 1000 verglichen wird.