2009-03-02 4 views
2

Ich habe erlebt, was ein Schaltjahr in .NET DateTime Handhabung sein kann, speziell ToLocalTime(). Hier ist ein Code, der das Problem reproduziert (I in der pazifischen Zeitzone bin):Schaltjahr Bug Aufruf ToUniversalTime(). AddYears(). ToLocalTime()?

DateTime dtStartLocal = DateTime.Parse("2009-02-28T23:00:00.0-08:00"); 
DateTime dtEndLocal = dtStartLocal.AddYears(3); 
DateTime dtStartUtc = dtStartLocal.ToUniversalTime(); 
DateTime dtEndUtc = dtStartUtc.AddYears(3); 
DateTime dtEndLocal2 = dtEndUtc.ToLocalTime(); 
DateTime dtStartLocal2 = dtStartUtc.ToLocalTime(); 
Console.WriteLine("START: 1={0}, 2={0}", dtStartLocal, dtStartLocal2); 
Console.WriteLine("END : 1={0}, 2={1}", dtEndLocal, dtEndLocal2); 
Console.ReadLine(); 

Die Ausgabe lautet:

START: 1 = 2/28/2009 11.00.00 , 2 = 2/28/2009 23.00.00
END: 1 = 2/28/2012 11:00:00 PM, 2 = 2/29/2012 23.00.00

Beachten Sie die Variable, die ich ToUniversalTime().AddYears(3).ToLocalTime() anders als nur AddYears(3) war, ist es einen Tag voraus.

Hat jemand dies festgestellt? Wenn dies erwartet wird, kann jemand die Logik dahinter erklären?

HINWEIS: Ja, der beste Ansatz ist es, vollständig in UTC zu arbeiten und nicht Flipflop zwischen ihnen. Das ist nicht etwas, was mich betrifft, sondern eine Besonderheit, der ich begegnet bin. Im Wesentlichen habe ich missverstanden, wie AddYears() funktioniert und jetzt kann ich sehen, warum es tut, was es tut (siehe meine ausgewählte Antwort unten).

Antwort

9

Ich denke, dass dies richtig funktioniert.

DateTime dtStartUtc = dtStartLocal.ToUniversalTime(); 

PST ist UTC-8. Daher konvertiert dies die Zeit bis 1. März 2009, 07:00:00.

DateTime dtEndUtc = dtStartUtc.AddYears(3); 

Dies fügt drei Jahre zu der vorherigen Zeit hinzu und setzt es auf 1. März 2012, 07:00:00.

DateTime dtEndLocal2 = dtEndUtc.ToLocalTime(); 

Dies konvertiert die Endzeit zurück in PST, die 29. Februar 2012 11:00:00 wäre.

Ich würde sagen, dies ist nur ein Nebeneffekt der Konvertierung zwischen lokalen und UTC-Zeit.

+0

Schöne Erklärung. Dies ist ein gutes Beispiel dafür, warum Sie UTC-Datumsangaben für Ihre Datumsarithmetik verwenden sollten. –

+0

Nein, dies ist ein gutes Beispiel dafür, warum Datumsarithmetik in verschiedenen Zeitzonen schlecht ist. Sie können jede Operation in Ortszeit durchführen und trotzdem das gleiche Ergebnis erhalten, als ob Sie es in UTC gemacht hätten. Solange du konsequent bist, ist es egal. – Whatsit

+0

@Whatsit: in diesem Fall ja, aber wenn wir hinzufügen DST in den Mix, UTC ist der einzige vernünftige Weg –

0

Zeitzone/Korrekturfaktor drucken. Wenn Sie die .ToUniversialTime() -Methode ausführen, werden im Wesentlichen die 8 Stunden von Ihrer ursprünglichen Uhrzeit ("-08: 00") addiert, was am nächsten Tag um 23:00 Uhr, also am 28. Februar um 23:00 Uhr, bedeutet. Wenn du also 3 Jahre hinzufügst, ist es der 11.00 Uhr am 29.. Hätten Sie 2 Jahre gemacht, wäre es der 1. März gewesen, es hat nichts mit dem Schaltjahr zu tun.

0

Dieses Verhalten ist nicht falsch, soweit ich das beurteilen kann. Wenn Sie die lokale Zeit in UTC konvertieren, wird sie effektiv in den nächsten Tag verschoben. 1. März. Wenn Sie drei Jahre hinzufügen, bleibt es wie der 1. März. Rechnen Sie es zurück in die Ortszeit und es wird auf den vorherigen Tag zurückgerollt, der, weil 2012 ein Schaltjahr ist, der 29. Februar ist.