Domanda

Come funziona la conversione in UTC dal formato standard DateTime ?

Più specificamente, se creo un oggetto DateTime in un fuso orario e poi passo a un altro fuso orario ed eseguo ToUniversalTime () , come fa a sapere il la conversione è stata eseguita correttamente e che il tempo è ancora rappresentato con precisione?

È stato utile?

Soluzione

Non esiste un fuso orario implicito associato a un oggetto DateTime . Se si esegue ToUniversalTime () , utilizza il fuso orario del contesto in cui è in esecuzione il codice.

Ad esempio, se creo un DateTime dall'epoca dell'1 / 1/1970, mi dà lo stesso oggetto DateTime indipendentemente da dove mi trovo nel mondo .

Se eseguo ToUniversalTime () quando eseguo il codice a Greenwich, ottengo lo stesso tempo. Se lo faccio mentre vivo a Vancouver, ottengo un oggetto DateTime offset di -8 ore.

Ecco perché è importante archiviare le informazioni relative all'ora nel database come orari UTC quando è necessario eseguire qualsiasi tipo di conversione o localizzazione della data. Considera se la tua base di codice è stata spostata in una struttura server in un altro fuso orario;)

Modifica: nota dalla risposta di Joel - gli oggetti DateTime per impostazione predefinita sono digitati come DateTimeKind.Local . Se analizzi una data e la imposti come DateTimeKind.Utc , ToUniversalTime () non esegue alcuna conversione.

Ed ecco un articolo su " Best Practice Coding with Date Time " e un articolo su Conversione di DateTime con .Net .

Altri suggerimenti

In primo luogo, controlla se il Kind del DateTime è già noto come UTC. In tal caso, restituisce lo stesso valore.

Altrimenti, si presume che sia l'ora locale: è locale per il computer su cui è in esecuzione, e in particolare nel fuso orario che il computer stava usando quando alcune proprietà private sono state inizializzate pigramente. Ciò significa che se modifichi il fuso orario dopo l'applicazione è stata avviata, ci sono buone probabilità che continuerà a utilizzare quella precedente.

Il fuso orario contiene informazioni sufficienti per convertire l'ora locale in ora UTC o viceversa, anche se ci sono momenti ambigui o non validi. (Esistono orari locali che si verificano due volte e orari locali che non si verificano mai a causa dell'ora legale.) Le regole per la gestione di questi casi sono specificate in la documentazione :

  

Se il valore dell'istanza di data e ora è   un tempo ambiguo, presuppone questo metodo   che è un tempo standard. (Un   il tempo ambiguo può essere mappato   a un'ora standard o a   ora legale nell'ora locale   zona) Se l'istanza di data e ora   il valore è un tempo non valido, questo metodo   sottrae semplicemente l'ora locale da   l'offset UTC del fuso orario locale su   restituire UTC. (Un tempo non valido è uno   che non esiste a causa del   applicazione dell'ora legale   regole di adeguamento.)

Il valore restituito avrà un Kind di DateTimeKind.Utc , quindi se chiami ToUniveralTime per non applicare l'offset ancora. (Questo è un grande miglioramento rispetto a .NET 1.1!)

Se si desidera un fuso orario non locale, è necessario utilizzare < code> TimeZoneInfo che è stato introdotto in .NET 3.5 (ci sono soluzioni hacky per le versioni precedenti, ma non sono belle). Per rappresentare un istante nel tempo, è consigliabile utilizzare DateTimeOffset che è stato introdotto in .NET 2.0SP1, .NET3.0SP1 e .NET 3.5. Tuttavia, questo non ha ancora un fuso orario effettivo associato - solo un offset da UTC. Ciò significa che non sai quale sarà l'ora locale un'ora dopo, ad esempio - le regole dell'ora legale possono variare tra i fusi orari che hanno usato lo stesso offset per quel particolare istante. TimeZoneInfo è progettato per tenere conto delle regole storiche e future, al contrario di TimeZone che è in qualche modo semplicistico.

Fondamentalmente il supporto in .NET 3.5 è molto meglio di prima, ma lascia comunque a desiderare per una corretta aritmetica del calendario. Qualcuno ha il porting Joda Time su .NET? ;)

Cosa @womp ha detto , con l'aggiunta che controlla la proprietà Kind di DateTime per vedere se potrebbe già essere una data UTC.

DateTime.ToUniversalTime rimuove l'offset del fuso orario del fuso orario locale per normalizzare un DateTime in UTC. Se quindi usi DateTime.ToLocalTime sul valore normalizzato in un altro fuso orario, l'offset del fuso orario di quel fuso orario verrà aggiunto al valore normalizzato per la rappresentazione corretta in quel fuso orario.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top