DateTimeOffset
è una rappresentazione del tempo istantaneo (noto anche come tempo assoluto ). Con ciò intendo un momento nel tempo che è universale per tutti (senza tenere conto dei secondi bisestili o degli effetti relativistici della dilatazione del tempo ). Un altro modo per rappresentare il tempo istantaneo è con un DateTime
dove si .Kind
trova DateTimeKind.Utc
.
Questo è distinto dal tempo di calendario (noto anche come tempo civile ), che è una posizione sul calendario di qualcuno e ci sono molti calendari diversi in tutto il mondo. Chiamiamo questi fusi orari dei calendari . L'ora del calendario è rappresentata da un DateTime
dove si .Kind
trova DateTimeKind.Unspecified
o DateTimeKind.Local
. Ed .Local
è significativo solo in scenari in cui hai una comprensione implicita di dove è posizionato il computer che sta usando il risultato. (Ad esempio, una workstation dell'utente)
Quindi, allora, DateTimeOffset
invece di un UTC DateTime
? Si tratta di prospettiva. Usiamo un'analogia: faremo finta di essere fotografi.
Immagina di essere in piedi su una sequenza temporale del calendario, puntando una telecamera verso una persona sulla sequenza temporale istantanea disposta di fronte a te. Allinea la tua fotocamera in base alle regole del tuo fuso orario, che cambiano periodicamente a causa dell'ora legale o di altre modifiche alla definizione legale del tuo fuso orario. (Non hai una mano ferma, quindi la tua fotocamera è traballante.)
La persona in piedi nella foto vedrebbe l'angolazione da cui proveniva la tua fotocamera. Se gli altri stessero fotografando, potrebbero essere da angolazioni diverse. Questo è ciò che rappresenta la Offset
parte del DateTimeOffset
.
Quindi, se etichetti la tua fotocamera "Eastern Time", a volte stai puntando da -5 e a volte stai puntando da -4. Esistono telecamere in tutto il mondo, tutte etichettate in modo diverso e tutte puntate sulla stessa timeline istantanea da angolazioni diverse. Alcuni di essi si trovano uno accanto all'altro (o uno sopra l'altro), quindi è sufficiente conoscere l'offset per determinare a quale fuso orario è correlato il tempo.
E che dire di UTC? Bene, è l'unica fotocamera là fuori che è garantita per avere una mano ferma. È su un treppiede, saldamente ancorato al terreno. Non sta andando da nessuna parte. Chiamiamo il suo angolo di prospettiva l'offset zero.
Quindi, cosa ci dice questa analogia? Fornisce alcune linee guida intuitive
Se stai rappresentando il tempo relativo a un luogo in particolare, rappresentalo nel tempo di calendario con a DateTime
. Basta essere sicuri di non confondere mai un calendario con un altro. Unspecified
dovrebbe essere il tuo presupposto. Local
è utile solo venire DateTime.Now
. Ad esempio, potrei ottenerlo DateTime.Now
e salvarlo in un database, ma quando lo recupero, devo presumere che lo sia Unspecified
. Non posso fare affidamento sul fatto che il mio calendario locale è lo stesso calendario da cui è stato originariamente preso.
Se devi essere sempre certo del momento, assicurati di rappresentare il tempo istantaneo. Utilizzare DateTimeOffset
per applicarlo o utilizzare UTC DateTime
per convenzione.
Se devi tenere traccia di un momento di tempo istantaneo, ma vuoi anche sapere "A che ora ha pensato l'utente che fosse sul suo calendario locale?" - allora devi usare a DateTimeOffset
. Questo è molto importante per i sistemi di cronometraggio, ad esempio, sia per problemi tecnici che legali.
Se hai mai bisogno di modificarne uno precedentemente registrato DateTimeOffset
, non hai abbastanza informazioni nell'offset da solo per assicurarti che il nuovo offset sia ancora rilevante per l'utente. Devi anche memorizzare un identificatore del fuso orario (pensa: ho bisogno del nome di quella fotocamera per poter scattare una nuova foto anche se la posizione è cambiata).
Va anche sottolineato che Noda Time ha una rappresentazione richiesta ZonedDateTime
per questo, mentre la libreria di classi base .Net non ha nulla di simile. Dovresti archiviare sia DateTimeOffset
un TimeZoneInfo.Id
valore che un valore.
Occasionalmente, vorrai rappresentare un orario di calendario locale per "chiunque lo guardi". Ad esempio, quando si definisce cosa significa oggi . Oggi è sempre da mezzanotte a mezzanotte, ma rappresentano un numero pressoché infinito di intervalli sovrapposti sulla linea temporale istantanea. (In pratica abbiamo un numero finito di fusi orari, ma puoi esprimere gli offset fino al segno di spunta) Quindi in queste situazioni, assicurati di capire come limitare il "chi sta chiedendo?" fare una domanda in un unico fuso orario o occuparsi di tradurli di nuovo in tempo istantaneo come appropriato.
Ecco alcuni altri piccoli dettagli su DateTimeOffset
questo backup di questa analogia e alcuni suggerimenti per mantenerlo chiaro:
Se si confrontano due DateTimeOffset
valori, vengono prima normalizzati a zero offset prima del confronto. In altre parole, 2012-01-01T00:00:00+00:00
e si 2012-01-01T02:00:00+02:00
riferiscono allo stesso momento istantaneo e sono quindi equivalenti.
Se si sta eseguendo test di unità e si deve essere certi dell'offset, verificare sia il DateTimeOffset
valore che la .Offset
proprietà separatamente.
Esiste una conversione implicita unidirezionale incorporata nel framework .Net che consente di passare a DateTime
qualsiasi DateTimeOffset
parametro o variabile. Nel fare ciò, le .Kind
cose . Se si passa un tipo UTC, verrà eseguito con un offset zero, ma se si passa uno .Local
o o .Unspecified
, assumerà che sia locale . Fondamentalmente il framework sta dicendo: "Beh, mi hai chiesto di convertire il tempo del calendario in tempo istantaneo, ma non ho idea da dove provenga, quindi userò solo il calendario locale". Questo è un grosso problema se si carica un non specificato DateTime
su un computer con un fuso orario diverso. (IMHO - che dovrebbe generare un'eccezione - ma non lo fa.)
Spina senza vergogna:
Molte persone hanno condiviso con me che trovano questa analogia estremamente preziosa, quindi l'ho inclusa nel mio corso Pluralsight, Date and Time Fundamentals . Troverai una procedura dettagliata dell'analogia della telecamera nel secondo modulo, "Context Matters", nella clip intitolata "Tempo calendario vs. tempo istantaneo".