.NET definiert ist Spuren einige Geschichte, aber es ist nicht immer genau. Sie sind auf eine der Ungenauigkeiten gestoßen.
.NET importiert alle Zeitzoneninformationen von Windows über die Registrierung, wie beschrieben here und here. Wenn Sie in der Registrierung unter HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones\Russian Standard Time\Dynamic DST
suchen, werden Sie feststellen, dass nur Informationen von 2010 für diese Zeitzone nachverfolgt werden. Die Testdaten im Jahr 2000 werden nicht gut funktionieren, da sie auf die früheste verfügbare Regel (2010) zurückgehen werden.
Basis UTC Offset-Informationen in der Registrierung verfolgt, aber nicht in der AdjustmentRule
Klasse, die .NET es in importiert. Wenn Sie die Anpassungsregeln für diese Zeitzone überprüfen, werden Sie feststellen, dass 2012 und 2013 werden nicht importiert:
var tz = TimeZoneInfo.FindSystemTimeZoneById("Russian Standard Time");
foreach (var rule in tz.GetAdjustmentRules())
{
Console.WriteLine("{0:d} - {1:d}", rule.DateStart, rule.DateEnd);
}
OUTPUT:
1/1/0001 - 12/31/2010
1/1/2011 - 12/31/2011
1/1/2014 - 12/31/2014
Auch wenn sie in der Windows-Registrierung vorhanden ist, 2012 und 2013 werden nicht importiert, da sie keine Sommerzeiteinstellungen haben.
Dies erzeugt ein Problem, wenn sich der Basisoffset ändert - wie für diese Zeitzone. Da es derzeit +3 ist und die zwei Jahre, in denen es +4 war, nicht importiert wurden, wird es für die fehlenden Jahre wie +3 aussehen.
Es gibt keine gute Lösung dafür mit TimeZoneInfo
. Selbst wenn Sie versuchen, Ihre eigenen benutzerdefinierten Zeitzonen zu erstellen, werden Sie Schwierigkeiten haben, diese Art von Änderung in die verfügbaren Datenstrukturen einzubauen.
Zum Glück gibt es eine andere Option. Sie können den Standard IANA time zones über die Bibliothek Noda Time verwenden.
Der folgende Code verwendet Noda Zeit zu entsprechen, was Sie in Ihrem ursprünglichen Code geschrieben haben:
:
DateTimeZone tz = DateTimeZoneProviders.Tzdb.GetSystemDefault();
Console.WriteLine(Instant.FromUtc(2012, 1, 1, 0, 0).InZone(tz).LocalDateTime);
Console.WriteLine(Instant.FromUtc(2012, 6, 1, 0, 0).InZone(tz).LocalDateTime);
Console.WriteLine(Instant.FromUtc(2000, 1, 1, 0, 0).InZone(tz).LocalDateTime);
Console.WriteLine(Instant.FromUtc(2000, 6, 1, 0, 0).InZone(tz).LocalDateTime);
Wenn Ihre lokale Zeitzone nicht bereits für Moskau eingestellt ist, können Sie die erste Zeile ändern
DateTimeZone tz = DateTimeZoneProviders.Tzdb["Europe/Moscow"];
OUTPUT:
1/1/2012 4:00:00 AM
6/1/2012 4:00:00 AM
1/1/2000 3:00:00 AM
6/1/2000 4:00:00 AM
aktualisieren
Das oben beschriebene Problem von AdjustmentRule
Verfolgen Base Offset-Änderungen wurde in Microsoft Support-Artikel KB3012229 beschrieben und anschließend in .NET Framework 4.6 und .NET Core behoben.
In the reference sources kann man sehen, dass AdjustmentRule
jetzt ein m_baseUtcOffsetDelta
Feld hält. Obwohl dieses Feld nicht über eine öffentliche Eigenschaft verfügbar gemacht wird, spielt es bei den Berechnungen eine Rolle, und es spiegelt sich in der Serialisierung wider, wenn Sie die Methoden FromSerializedString
und ToSerializedString
verwenden (falls tatsächlich jemand diese verwendet).
Werfen Sie einen Blick auf 'DateTimeOffset'. *** Wenn *** Sie den Zeitzonen-Offset erfassen können, während Sie die Daten erfassen, sind Sie besser in der Lage, sie anzuzeigen und dagegen zu berechnen. –