Any () -Methode für ListDateTime funktioniert nicht erwartungsgemäß

9

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:

    
Amit 08.03.2018, 06:54
quelle

5 Antworten

21

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:

%Vor%

Dadurch werden die Eigenschaften Ticks und TimeOfDay Ihrer dateNow gleich denen, die Sie Ihrer dateTimeList hinzugefügt haben.

    
S.Akbari 08.03.2018, 07:14
quelle
39

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.

    
Eric Lippert 08.03.2018 07:20
quelle
10

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:

%Vor%

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:

%Vor%

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.

%Vor%

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.

    
Sweeper 08.03.2018 07:17
quelle
2

Problem

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.

Eine Lösung

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%

Beiseite

Wir können eine Datumszeichenfolge mit der Genauigkeit von Ticks formatieren, indem Sie fffffff anstelle von fff .

    
Shaun Luttin 08.03.2018 07:40
quelle
0

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%     
controlbox 08.03.2018 16:32
quelle

Tags und Links