Memorizzazione di DateTime (UTC) e archiviazione di DateTimeOffset


95

Di solito ho un "intercettore" che proprio prima di leggere / scrivere dal / al database esegue la conversione di DateTime (da UTC a ora locale e da ora locale a UTC), quindi posso utilizzare DateTime.Now(derivazioni e confronti) in tutto il sistema senza preoccuparmi sui fusi orari.

Per quanto riguarda la serializzazione e lo spostamento di dati tra computer, non è necessario preoccuparsi, poiché il datetime è sempre UTC.

Devo continuare a memorizzare le mie date (SQL 2008 - datetime) in formato UTC o dovrei invece memorizzarle utilizzando DateTimeOffset(SQL 2008 - datetimeoffset)?

Le date UTC nel database (tipo datetime) funzionano e sono note da così tanto tempo, perché cambiarle? Quali sono i vantaggi?

Ho già esaminato articoli come questo , ma non ne sono convinto al 100%. qualche idea?



1
Vedi anche: DateTime vs DateTimeOffset - scritto per .Net, ma concettualmente si applica anche a SQL.
Matt Johnson-Pint

Risposte:


131

C'è un'enorme differenza, in cui non puoi usare UTC da solo.

  • Se hai uno scenario come questo

    • Un server e diversi client (tutti geograficamente in fusi orari diversi )
    • I client creano alcuni dati con informazioni datetime
    • I client memorizzano tutto sul server centrale
  • Poi:

    • datetimeoffset memorizza l'ora locale del client e anche l'offset all'ora UTC
    • tutti i clienti conoscono l'ora UTC di tutti i dati e anche l'ora locale nel luogo in cui hanno avuto origine le informazioni
  • Ma:

    • Datetime UTC memorizza solo datetime UTC , quindi non hai informazioni sull'ora locale nella posizione del client in cui hanno avuto origine i dati
    • Altri client non conoscono l'ora locale del luogo, da cui provengono le informazioni datetime
    • Gli altri client possono solo calcolare la loro ora locale dal database (utilizzando l'ora UTC) non l'ora locale del client, dove hanno avuto origine i dati

Un semplice esempio è il sistema di prenotazione dei biglietti aerei ... Il biglietto aereo deve contenere 2 orari: - orario di "decollo" (nel fuso orario della città "Da") - ora di "atterraggio" (nel fuso orario della città "Destinazione")


2
Questa è la migliore spiegazione di cui ho letto quando sarebbe stata appropriata, e ho letto molto Per noi, da questo, non sembra così. Otteniamo l'ora in UTC per i nostri dati esterni e, se necessario, conosciamo la posizione da un'altra fonte (e non lo è mai stata). Grazie per averlo fatto sembrare così ovvio.
Andrew Backer,

19
hai detto "datetimeoffset memorizza l'ora UTC e ANCHE l'offset rispetto all'ora locale del client", ma datetimeoffset memorizza ora LOCALE + offset, o ora UTC + offset uguale a +0.
Serhii Kyslyi

anche se potresti semplicemente trasmettere il DTO a un DT poiché la base DT è UTC (sebbene questo sarebbe un passaggio aggiuntivo per tutti coloro che utilizzano il database e probabilmente non è più semplice del solo utilizzo dell'ora UTC)
iliketocode

2
Sembra più come DateTmeOffset memorizza "Ora locale e offset UTC", non "Ora UTC e offset UTC". Se si esegue il cast a datetime o si utilizza una delle funzioni datepart, si ottengono i componenti di data e ora locali.
Triynko

" tutti i clienti conoscono l'ora UTC di tutti i dati e anche l'ora locale nel luogo in cui hanno avuto origine le informazioni" Anche se la memorizzazione come parte del campo della data sembra non normalizzata in quel caso. Qual è il caso d'uso, ovvero perché non dovresti usare UTC e estrarre l'offset a InputLocationId(o un'entità normalizzata simile). Ci sarebbero calcoli coinvolti (ciao, eccezioni ... specialmente tu, Indiana ), ma è ancora un processo deterministico - e quindi l'equilibrio della logica datetime dell'app è semplice.
ruffin

23

Hai assolutamente ragione nell'usare l'UTC per tutti i tempi storici (ovvero la registrazione di eventi accaduti). È sempre possibile passare da UTC a ora locale, ma non sempre il contrario.

Quando utilizzare l'ora locale? Rispondi a questa domanda:

Se il governo decide improvvisamente di cambiare l'ora legale, vorresti che questi dati cambiassero con essa?

Memorizza l'ora locale solo se la risposta è "sì". Ovviamente ciò sarà solo per date future, e di solito solo per date che influenzano le persone in qualche modo.

Perché memorizzare un fuso orario / offset?

In primo luogo, se si desidera registrare qual è stato lo scostamento per l'utente che ha eseguito l'azione, probabilmente sarebbe meglio farlo, ovvero al login registrare la posizione e il fuso orario di quell'utente.

In secondo luogo, se vuoi convertire per la visualizzazione, devi avere una tabella di tutte le transizioni di offset dell'ora locale per quel fuso orario, semplicemente sapere che l'offset corrente non è sufficiente, perché se stai mostrando una data / ora di sei mesi fa l'offset lo farà essere diverso.


4
La conversione da Windows UTC all'ora locale tiene conto del cambiamento dell'ora legale per le date storiche. Non vedo perché in questo caso vorresti memorizzare l'ora locale.
Jamiegs

1
@Jamiegs Windows conosce solo storicamente le "ultime informazioni storiche" (come suggerito / annotato nella documentazione di .NET DateTime). Non è completo.

2
ovviamente, devi anche memorizzare il luogo dell'evento, altrimenti non puoi dire in quale "ora locale" è avvenuto l'evento.
keuleJ

20

UN DATETIMEOFFSET ti dà la possibilità di memorizzare l'ora locale e l'ora UTC in un campo.

Ciò consente un reporting molto semplice ed efficiente in ora locale o UTC senza la necessità di elaborare i dati per la visualizzazione in alcun modo.

Questi sono i due requisiti più comuni: l'ora locale per i rapporti locali e l'ora UTC per i rapporti di gruppo.

L'ora locale è memorizzata nella parte DATETIME di DATETIMEOFFSET e l'offset da UTC è memorizzato nella porzione OFFSET, quindi la conversione è semplice e, poiché non richiede la conoscenza del fuso orario da cui provengono i dati, può essere eseguita a livello di database .

Se non si richiedono tempi fino a millisecondi, ad esempio solo minuti o secondi, è possibile utilizzare DATETIMEOFFSET (0). Il campo DATETIMEOFFSET richiederà quindi solo 8 byte di archiviazione, lo stesso di DATETIME.

L'utilizzo di un DATETIMEOFFSET invece di un UTC DATETIME offre quindi maggiore flessibilità, efficienza e semplicità per il reporting.


Peccato che il framework dell'entità non abbia alcun modo per accedere al datetime locale di un campo datetimeoffset, rendendo impossibile interrogare una data locale particolare.
Triynko

@Triynko puoi spiegare cosa intendi? Esempio?
reidLinden
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.