Ich arbeite an .net 4.6 in winforms (hier ist Code von der Testkonsolenanwendung)
An einer Stelle habe ich eine Liste von DateTime
und ich muss herausfinden, ob diese Liste bestimmtes Datum enthält oder nicht.
Dafür versuche ich Any()
in der Liste zu verwenden.
Auch wenn die Liste das gewünschte Datum enthält, gibt Any()
nur false
zurück.
Es folgt ein Beispielcode, die ebenfalls dasselbe Verhalten haben. Also, wenn ich eine Idee zu diesem Code bekomme, denke ich, dass es auch meinem echten Code helfen wird.
%Vor%Ausgabe:
Die Ticks
und < a href="https://msdn.microsoft.com/en-us/library/system.datetime.timeofday(v=vs.110).aspx"> TimeOfDay
Eigenschaften von Elementen in Ihrem dateTimeList
ist nicht gleich Ticks
und TimeOfDay
Eigenschaften von dateNow
, und dateNow
hat mehr Ticks als das in dateTimeList
. Sie müssen diese Zeile hinzufügen:
Dadurch werden die Eigenschaften Ticks
und TimeOfDay
Ihrer dateNow
gleich denen, die Sie Ihrer dateTimeList
hinzugefügt haben.
Es gibt ein Sprichwort in der Computerprogrammierung "Auswahl ist nicht kaputt". Es bedeutet, dass wenn ein grundlegendes, häufig verwendetes, stark getestetes Bit der Software kaputt zu sein scheint, das Problem darin besteht, dass Sie das Problem falsch diagnostiziert haben, nicht, dass das Tool defekt ist.
Any
funktioniert gut.
Der Fehler ist, dass Sie das Datum korrekt an einer Stelle und falsch an der anderen Stelle runden und das falsch gerundete Datum nicht mit dem korrekt gerundeten Datum übereinstimmt. Verwenden Sie die Ticks
-Eigenschaft an den Daten, um zu sehen, warum eine Ihrer Rundungstechniken gut ist und eine davon völlig falsch ist.
Der Schlüssel zum Herausfinden, warum dies geschieht, ist herauszufinden, was der Unterschied zwischen den beiden DateTime
s ist, die wir vergleichen.
Wenn Sie die Ticks
-Eigenschaft des Datums mal ausdrucken, finden Sie in etwa folgendes:
Wie Sie sehen können, sind diese beiden Zeilen wahrscheinlich die beiden DateTime
s, von denen Sie denken, dass sie gleich wären, aber nicht:
Die obige ist dateNow
und die untere ist die in der Liste.
Siehst du den Unterschied? dateNow
hat mehr Ticks als der in der Liste.
Warum ist das?
Die DateTime
s in der Liste werden aus date
erstellt, das mit dem Konstruktor mit 6 Argumenten erstellt wird. Dies erstellt ein DateTime
genau wie du es spezifiziert hast. Dies bedeutet, dass die erstellte Instanz keine zusätzlichen Ticks für den "Rest" hat. Und ich kann sehen, dass Sie, wenn Sie Ihre dateNow
ändern, versucht haben, alle zusätzlichen Komponenten zu entfernen, die Sie nicht interessieren, wie Sekunden und Millisekunden, aber Sie haben Ticks vergessen. Wenn Sie 2 DateTime
s vergleichen, vergleichen Sie tatsächlich die Ticks.
Sie müssen also die zusätzlichen Ticks von Ihrem dateNow
entfernen, um das gewünschte Ergebnis zu erhalten, oder einfach den 6-Argument-Konstruktor erneut verwenden.
Ihre Synchronisation mit AddSeconds
und AddMilliseconds
funktioniert mit der Genauigkeit von fff
(Millisekunden), aber nicht mit der Genauigkeit von Ticks
(ein Zehnmillionstel Sekunde). Letzteres ist erforderlich für die DateTime
Gleichheit , die Any()
verwendet.
Synchronisieren Sie die Kopie DateTime
mit ihrem Prototyp, indem Sie diese Kopie mit der DateTime
Konstruktor, der Ticks
benötigt. Dann findet Ihr Code genau das Datum mit Any()
.
Hier ist Ihr verbesserter Code als funktionierende Fiddle .
%Vor% Wir können eine Datumszeichenfolge mit der Genauigkeit von Ticks formatieren, indem Sie fffffff
anstelle von fff
.
DateTime verwendet die Systemuhr , die notorisch nur ungefähr 10-15ms entspricht - wie in der Antwort auf diese Frage hervorgehoben - < a href="https://stackoverflow.com/questions/16032451/get-datetime-now-with-milliseconds-precision"> Get DateTime.Now mit Millisekunden Genauigkeit
Um das zu umgehen, müssen Sie Ihren Gleichheitsvergleich (==) in Ihrer Any () -Klausel durch eine Prüfung ersetzen, die die Ungewissheit berücksichtigt. Der folgende Code stimmt mit den Daten überein, wenn sie weniger als 20ms voneinander entfernt sind ...
%Vor%