Ottieni fuso orario da DateTime


103

.Net DateTime contiene informazioni sul fuso orario in cui è stato creato?

Ho una libreria che analizza DateTime da un formato che ha "+ zz" alla fine, e mentre analizza correttamente e regola l'ora locale, ho bisogno di ottenere quale fosse il fuso orario specifico dall'oggetto DateTime.

Ciò è effettivamente possibile? Tutto quello che posso vedere è DateTime.Kind, che specifica se l'ora è locale o UTC.


Vedere le note sulla documentazione di DateTime.Parse per la gestione dei fusi orari e DateTimeStyles. Ma no, quello che vuoi non è davvero possibile.
yoyo

Risposte:


136

DateTime stesso non contiene informazioni sul fuso orario reale. Si può sapere se è UTC o locale, ma non quello che realmente locale mezzi.

DateTimeOffset è un po 'meglio: è fondamentalmente un'ora UTC e un offset. Tuttavia, questo non è ancora abbastanza per determinare il fuso orario, poiché molti fusi orari diversi possono avere lo stesso offset in qualsiasi momento. Sembra che possa essere abbastanza buono per te, poiché tutto ciò con cui devi lavorare quando parli di data / ora è l'offset.

Il supporto per i fusi orari a partire da .NET 3.5 è molto migliore di quanto non fosse, ma mi piacerebbe davvero vedere un "ZonedDateTime" standard o qualcosa del genere: un'ora UTC e un fuso orario effettivo. È facile crearne uno personalizzato, ma sarebbe bello vederlo nelle librerie standard.

EDIT: Quasi quattro anni dopo, ora suggerirei di utilizzare Noda Time che ha un set piuttosto più ricco di tipi di data / ora. Sono di parte, però, come l'autore principale di Noda Time :)


2
Il progetto PublicDomain su CodePlex lo fa per te.
Cheeso

Un'enumerazione TimeZone nella BCL sarebbe utile se i fusi orari mondiali fossero statici e non cambiassero.
Jeff LaFay

1
@jlafay: Tuttavia, cambiano: più fusi orari sono stati aggiunti a Windows solo l'anno scorso, ad esempio.
Jon Skeet,

Questo progetto non è più mantenuto dall'autore; publicdomain.codeplex.com Sembra che forse questo potrebbe aiutare, a seconda dell'uso, è necessario impostarlo prima di usarlo; timezone.codeplex.com
AnneTheAgile

3
@AnneTheAgile: Personalmente consiglierei di usare la mia libreria Noda Time, ovviamente :)
Jon Skeet

36

No.

Uno sviluppatore è responsabile di tenere traccia delle informazioni sul fuso orario associate a un valore DateTime tramite un meccanismo esterno.

Una citazione da un ottimo articolo qui . Una lettura obbligata per ogni sviluppatore .Net.

Quindi il mio consiglio è di scrivere una piccola lezione di wrapper che si adatti alle tue esigenze.



2

Potresti usare la classe TimeZoneInfo

La classe TimeZone riconosce il fuso orario locale e può convertire l'ora tra l'ora UTC (Coordinated Universal Time) e l'ora locale. Un oggetto TimeZoneInfo può rappresentare qualsiasi fuso orario e i metodi della classe TimeZoneInfo possono essere utilizzati per convertire l'ora in un fuso orario nell'ora corrispondente in qualsiasi altro fuso orario. I membri della classe TimeZoneInfo supportano le operazioni seguenti:

  1. Recupero di un fuso orario già definito dal sistema operativo.

  2. Enumerazione dei fusi orari disponibili su un sistema.

  3. Conversione dei tempi tra diversi fusi orari.

  4. Creazione di un nuovo fuso orario che non è già definito dal sistema operativo.

    Serializzazione di un fuso orario per il successivo recupero.


1
... ma, dato un DateTime, non c'è ancora un modo per utilizzare TimeZoneInfo per determinare il TimeZone di DateTime, per quanto ne so.
Remi Despres-Smyth

@ RemiDespres-Smyth Memorizzo semplicemente TimeZoneInfo insieme a DateTime in 1 classe.
Konrad


0

Generalmente la pratica sarebbe passare i dati come DateTime con un "fuso orario" di UTC e quindi passare un oggetto TimeZoneInfo e quando si è pronti per visualizzare i dati, si utilizza l'oggetto TimeZoneInfo per convertire il DateTime UTC.

L'altra opzione è impostare DateTime con il fuso orario corrente, quindi assicurarsi che il "fuso orario" sia sconosciuto per l'oggetto DateTime, quindi assicurarsi che DateTime venga nuovamente passato con un TimeZoneInfo che indichi il TimeZone del DateTime passato.

Come altri hanno indicato qui, sarebbe bello se Microsoft se ne occupasse e creasse un oggetto carino per fare tutto, ma per ora devi occuparti di due oggetti.


0

DateTime non conosce la differenza di fuso orario. Non esiste un metodo integrato per restituire l'offset o il nome del fuso orario (ad esempio EAT, CEST, EST ecc.).

Come suggerito da altri, puoi convertire la tua data in UTC:

DateTime localtime = new DateTime.Now;
var utctime = localtime.ToUniversalTime();

e quindi calcola solo la differenza:

TimeSpan difference = localtime - utctime;

Inoltre puoi convertire una volta in un'altra usando DateTimeOffset:

DateTimeOffset targetTime = DateTimeOffset.Now.ToOffset(new TimeSpan(5, 30, 0));

Ma questa è una sorta di compressione con perdita di dati: il solo offset non è in grado di dirti quale fuso orario è poiché due paesi diversi possono trovarsi in fusi orari diversi e avere lo stesso orario solo per una parte dell'anno (ad es. Sud Africa ed Europa). Inoltre, tieni presente che l'ora legale estiva può essere introdotta in date diverse (EST vs CET - una differenza di 3 settimane).

È possibile ottenere il nome del fuso orario del sistema locale utilizzando la classe TimeZoneInfo:

TimeZoneInfo localZone = TimeZoneInfo.Local;
localZone.IsDaylightSavingTime(localtime) ? localZone.DaylightName : localZone.StandardName

Sono d'accordo con Gerrie Schenck, leggi l'articolo che ha suggerito.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.