userei Noda Time personalmente, ma se non si può fare che ...
usare sia DateTime.ParseExact
specificando il formato esatto che ci si aspetta, e comprendono DateTimeStyles.AssumeUniversal
e DateTimeStyles.AdjustToUniversal
nel codice parse:
using System;
using System.Globalization;
class Test
{
static void Main()
{
var date = DateTime.ParseExact("2012-09-30T23:00:00.0000000Z",
"yyyy-MM-dd'T'HH:mm:ss.fffffff'Z'",
CultureInfo.InvariantCulture,
DateTimeStyles.AssumeUniversal |
DateTimeStyles.AdjustToUniversal);
Console.WriteLine(date);
Console.WriteLine(date.Kind);
}
}
(abbastanza perché sarebbe un di norma senza AdjustToUniversal
è oltre me, ma non importa ...)
EDIT: Solo per espandere le mie obiezioni al suggerimento di mattytommo, ho mirato a dimostrare che avrebbe perso le informazioni. Ho fallito finora - ma in un modo molto particolare. Date un'occhiata a questo - in esecuzione nel fuso orario Europe/London, dove gli orologi tornano il 28 ottobre nel 2012, alle 02:00 ora locale (UTC 01:00):
DateTime local1 = DateTime.Parse("2012-10-28T00:30:00.0000000Z");
DateTime local2 = DateTime.Parse("2012-10-28T01:30:00.0000000Z");
Console.WriteLine(local1 == local2); // True
DateTime utc1 = TimeZoneInfo.ConvertTimeToUtc(local1);
DateTime utc2 = TimeZoneInfo.ConvertTimeToUtc(local2);
Console.WriteLine(utc1 == utc2); // False. Hmm.
Sembra che ci sia un "con o senza il flag "DST" memorizzato da qualche parte, ma sarò bloccato se riesco a capire dove. La documentazione per TimeZoneInfo.ConvertTimeToUtc
stato
Se dateTime corrisponde ad un tempo ambiguo, questo metodo presuppone che è il tempo standard del tempo sorgente orario.
Ciò non sembrano sia il caso qui durante la conversione local2
...
EDIT: Okay, diventa ancora più strano - dipende quale versione del quadro che si sta utilizzando. Considerate questo programma:
using System;
using System.Globalization;
class Test
{
static void Main()
{
DateTime local1 = DateTime.Parse("2012-10-28T00:30:00.0000000Z");
DateTime local2 = DateTime.Parse("2012-10-28T01:30:00.0000000Z");
DateTime utc1 = TimeZoneInfo.ConvertTimeToUtc(local1);
DateTime utc2 = TimeZoneInfo.ConvertTimeToUtc(local2);
Console.WriteLine(utc1);
Console.WriteLine(utc2);
DateTime utc3 = local1.ToUniversalTime();
DateTime utc4 = local2.ToUniversalTime();
Console.WriteLine(utc3);
Console.WriteLine(utc4);
}
}
Quindi questo richiede due diversi valori UTC, li analizza con DateTime.Parse
, poi li converte di nuovo a UTC in due modi diversi.
Risultati sotto .NET 3.5:
28/10/2012 01:30:00 // Look - we've lost information
28/10/2012 01:30:00
28/10/2012 00:30:00 // But ToUniversalTime() seems okay...
28/10/2012 01:30:00
risultati sotto .NET 4.5 beta:
28/10/2012 00:30:00 // It's okay!
28/10/2012 01:30:00
28/10/2012 00:30:00
28/10/2012 01:30:00
Un valore DateTime memorizza il suo tipo nei suoi due bit più significativi: Non specificato (00), Utc (01), Locale (10) e LocalAmbiguousDst (11). Tuttavia, LocalAmbiguousDst è esposto pubblicamente come Locale. –
@ MichaelLiu: Giusto. Quindi, finché non lo converti in universale, non puoi dire la differenza. Che bello. Ick. –
@JonSkeet Significa che il mio codice era corretto (ad eccezione di ParseExact) in quanto deve essere prima convertito in universale? – mattytommo