NET tracce della cronologia, ma non è sempre preciso. Sei incappato in una delle inesattezze.
.NET importa tutte le informazioni sul fuso orario da Windows tramite il registro, come descritto here e here. Se si guarda nel registro HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones\Russian Standard Time\Dynamic DST
, si scoprirà che tiene traccia solo delle informazioni dal 2010 in avanti per questo fuso orario. Le date dei test nell'anno 2000 non funzioneranno bene, poiché ricadranno nella prima regola disponibile (2010).
Base UTC compensata informazioni è rintracciato nel Registro di sistema, ma non nella classe AdjustmentRule
che .NET importa in. Se si controlla le regole di regolazione per questo fuso orario, troverete che il 2012 e il 2013 non vengono importate a tutti:
var tz = TimeZoneInfo.FindSystemTimeZoneById("Russian Standard Time");
foreach (var rule in tz.GetAdjustmentRules())
{
Console.WriteLine("{0:d} - {1:d}", rule.DateStart, rule.DateEnd);
}
USCITA:
1/1/0001 - 12/31/2010
1/1/2011 - 12/31/2011
1/1/2014 - 12/31/2014
Anche se esistono nel Registro di sistema di Windows, 2012 e 2013 non vengono importati perché non hanno regolazioni dell'ora legale.
Questo crea un problema quando lo scostamento di base cambia, come nel caso di questo fuso orario. Dal momento che è attualmente +3, e il due anni in cui era +4 non sono stati importati, sembrerà che sia stato +3 per gli anni mancanti.
Non c'è una buona soluzione per questo utilizzando TimeZoneInfo
. Anche se provi a creare i tuoi fusi orari personalizzati, avrai difficoltà ad inserire questo tipo di cambiamento nelle strutture dati disponibili.
Fortunatamente, c'è un'altra opzione. È possibile utilizzare lo standard IANA time zones tramite la libreria Noda Time.
Il codice seguente utilizza Noda tempo per abbinare quello che hai scritto nel codice originale:
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);
Se il fuso orario locale non è già impostato per Mosca, è possibile cambiare la prima linea a:
DateTimeZone tz = DateTimeZoneProviders.Tzdb["Europe/Moscow"];
USCITA:
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
Aggiornamento
0.123.516,410617 millions
Il problema descritto sopra di AdjustmentRule
che non rileva le variazioni di offset di base è stato descritto nell'articolo di supporto Microsoft KB3012229 e successivamente risolto in .NET Framework 4.6 e anche in .NET Core.
In the reference sources, si può vedere che AdjustmentRule
ora mantiene un campo m_baseUtcOffsetDelta
. Anche se questo campo non è esposto tramite una proprietà pubblica, esso fa riferimento ai calcoli e riflette nella serializzazione se si utilizzano i metodi FromSerializedString
e ToSerializedString
(se qualcuno li utilizza effettivamente).
Dai un'occhiata a "DateTimeOffset'. *** Se *** puoi catturare l'offset del fuso orario mentre acquisisci i dati sarai più in forma per visualizzarli e calcolare contro di essi. –