Qual è un caso d'uso valido per l'utilizzo di TIMESTAMP SENZA FUSO ORARIO?


41

C'è una risposta lunga e abbastanza chiara sulle differenze tra

  • TIMESTAMP WITH TIME ZONE -confrontarli-
  • TIMESTAMP WITHOUT TIME ZONE

disponibile in questo post SO . Quello che vorrei sapere è: ci sono casi d'uso validi per l'uso effettivo TIMESTAMP WITHOUT TIME ZONEo dovrebbero essere considerati un anti-pattern.


Questa domanda rischia di essere chiusa essendo "principalmente basata sull'opinione". Ho cercato di dare alcune opinioni obiettive nella mia risposta di seguito.
Colin 't Hart,

2
Questo problema è abbastanza reale, ogni tipo di dati ha un significato molto diverso. Quindi certamente non considererei questa domanda principalmente basata sull'opinione.
Basil Bourque,

Risposte:


30

Ciò viene affermato in un sacco di posti, ma credo che la pena ricordare sempre quando si confronta la timestamp with time zonecon timestamp without time zonetipi: il timestamp WITH time zonenon memorizzare il fuso orario informazioni con il timestamp . Ciò che fa è archiviare tutti i dati nel fuso orario UTC, come indicato nei documenti :

Per il timestamp con fuso orario, il valore memorizzato internamente è sempre in UTC (Universal Coordinated Time, tradizionalmente noto come Greenwich Mean Time, GMT). Un valore di input con un fuso orario esplicito specificato viene convertito in UTC utilizzando l'offset appropriato per quel fuso orario. Se nella stringa di input non viene indicato alcun fuso orario, si presume che si trovi nel fuso orario indicato dal parametro TimeZone del sistema e viene convertito in UTC utilizzando l'offset per il fuso orario.

È considerato valido per alcuni da utilizzare timestamp WITHOUT time zonein situazioni in cui (1) tutto è nello stesso fuso orario o (2) il livello applicazione gestisce il fuso orario e memorizza tutto in un determinato fuso orario (di solito UTC). Ma è anche considerato un anti-pattern, semplice perché la soluzione corretta per (1) è configurare l'impostazione TimeZone sul dato fuso orario per il sistema e (2) è già risolto, poiché PostgreSQL memorizza già tutto nello stesso fuso orario (UTC).

Ora, con quei due giù, posso venire con solo una buona ragione per usare timestamp WITHOUT time zone. Questo è quando si desidera archiviare eventi in futuro e quando si arriva a quel momento è necessario attivare una sorta di avviso. Ciò potrebbe essere utile timestamp WITH time zonese, e solo se, le regole definite dalle leggi regionali sul fuso orario non sono mai cambiate. La regola più comune che cambia riguarda l'adozione o meno dell'ora legale (DST).

Ad esempio, immagina di essere, diciamo, 2013-06-15(non ancora in ora legale) in programma di un evento 2013-01-15 10:00(che sarebbe già in ora legale), e nella 2013-06-15tua regione è stato designato di adottare l'ora legale; ma, qualche tempo dopo, il governo ha cambiato la regola e dice che la tua regione non utilizzerà più l'ora legale e improvvisamente il tuo orario programmato diventa 2013-01-15 11:00(invece di 10:00), che se usi timestamp WITH time zonee mantieni aggiornate le tue configurazioni TZ. Ovviamente potresti anche notare che è possibile trattare tali casi anche con il fuso orario, se tieni traccia delle modifiche alle regole nelle regioni / fusi orari di tuo interesse e aggiorni i record interessati.

Vale la pena ricordare che alcune regioni cambiano spesso queste regole (come in Brasile, alcuni stati - non l'intero paese - cambiano spesso), ma nella maggior parte dei casi lo cambiano molto prima, quindi i tuoi utenti sarebbero interessati solo da eventi programmati molto lontano da l'ora corrente.

Detto questo, ho solo un altro suggerimento. Se disponi di utenti, registri o altro su fusi orari diversi, archivia il fuso orario da cui provengono da qualche parte e scegli e utilizza timestamp with time zone. In questo modo è possibile (1) attraversare eventi che si verificano più vicini tra loro per fonti diverse (indipendentemente dai rispettivi fusi orari) e (2) mostrare l'ora originale (l'ora dell'orologio) in cui si è verificato l'evento.


Stai dicendo: "Posso venire con solo una buona ragione per usare il timestamp con il fuso orario". Se questo non è un refuso allora stai davvero suggerendo che "timestamp senza fuso orario" è in realtà più appropriato / meno incline a produrre incomprensioni di "timestamp con fuso orario"? A me sembra controintuitivo.
Marcus Junius Brutus,

@MarcusJuniusBrutus, scusami, era davvero un errore di battitura e ho pensato il contrario ... Controlla la risposta modificata.
Matheus,

codeblog.jonskeet.uk/2019/03/27/… discute in profondità esattamente questo scenario-regole-evento-futuro-potrebbe cambiare (con la stessa conclusione)
Beni Cherniavsky-Paskin

19

Sì. Ci sono casi d'uso per TIMESTAMP WITHOUT TIME ZONE.

  • Nelle comuni app aziendali questo tipo verrebbe utilizzato solo per:
    • Prenotazione appuntamenti futuri
    • Rappresenta la stessa ora del giorno in diversi fusi orari, come il mezzogiorno del 23 a Tokyo e a Parigi (due diversi momenti a ore, lo stesso giorno del giorno)
  • Per il monitoraggio momenti, punti specifici sulla timeline, utilizzare sempre TIMESTAMP WITH TIME ZONE, non è WITHOUT.

TIMESTAMP WITHOUT TIME ZONEi valori non sono un punto sulla sequenza temporale, non momenti reali. Rappresentano un'idea approssimativa di potenziali momenti, possibili punti della sequenza temporale in un intervallo di circa 26-27 ore (l'intervallo di fusi orari in tutto il mondo). Non hanno alcun significato reale fino a quando non si applica un fuso orario o un offset da UTC .

Es: Natale

Ad esempio, supponiamo che sia necessario registrare l'inizio delle festività / dei giorni sacri.

Table: holiday_

Column: year_         Type: SMALLINT
Column: description_  Type: VARCHAR
Column: start_        Type: TIMESTAMP WITHOUT TIME ZONE

Per registrare il fatto che il Natale inizia dopo la mezzanotte del 25 dicembre di quest'anno, dobbiamo dire 2016-12-25 00:00:00senza alcun fuso orario. All'inizio del giorno di Babbo Natale visita Auckland, in Nuova Zelanda, subito dopo mezzanotte, poiché questa è una delle prime notti di mezzanotte al mondo. Quindi si dirige verso ovest, come accade la mezzanotte successiva, raggiungendo presto le Filippine. Quindi le renne proseguono in direzione ovest, raggiungendo l'India alla sua mezzanotte che si verifica diverse ore dopo quella mezzanotte di Auckland. Molto più tardi è ancora mezzanotte a Parigi, Francia, e ancora più tardi a Montreal, in California. Tutte queste visite di Babbo Natale avvengono in momenti diversi è il momento , eppure sono avvenute poco dopo la mezzanotte, per la mezzanotte di ogni località.

Quindi registrare 2016-12-25 00:00:00senza alcun fuso orario come l'inizio del Natale è informativo e legittimo, ma solo vagamente. Finché non dici "Natale ad Auckland" o "Natale a Montréal", non abbiamo un momento preciso nel tempo. Se stai registrando il momento effettivo ogni volta che la slitta è atterrata, useresti TIMESTAMP WITH TIME ZONEpiuttosto che il WITHOUTtipo.

Simile al Natale è la vigilia di Capodanno. Quando la Times Square Ball scende a New York , la gente a Seattle sta ancora raffreddando il suo champagne e sta preparando le corna della sua festa . Eppure registreremmo l' idea del momento di Capodanno come 2017-01-01 00:00:00in a TIMESTAMP WITHOUT TIME ZONE. Al contrario, se vogliamo registrare quando la palla è caduta a New York, o quando la gente di Seattle ha suonato le corna, avremmo invece usato TIMESTAMP WITH TIME ZONE(non WITHOUT) per registrare quei momenti reali, a tre ore l'una dall'altra.

Es .: turni di fabbrica

Un altro esempio potrebbe essere la registrazione di una politica che prevede il tempo dell'orologio a muro in varie posizioni. Supponiamo di avere fabbriche a Detroit, Düsseldorf e Delhi. Se diciamo che in tutte e tre le fabbriche il primo turno inizia alle 6:00 con una pausa pranzo alle 11:30, ciò potrebbe essere registrato come TIMESTAMP WITHOUT TIME ZONE. Ancora una volta, queste informazioni sono utili in modo vago ma non indicano un momento specifico fino a quando non applicheremo un fuso orario. Un nuovo giorno sorge prima ad est. Quindi la fabbrica di Delhi sarà la prima ad aprire alle sue 6 del mattino. Ore dopo, la fabbrica di Düsseldorf inizia a lavorare alle 6:00. Ma la fabbrica di Detroit non aprirà fino a quando non saranno trascorse altre sei ore, quando saranno le 6 del mattino.

Contrasta questa idea (di quando generalmente inizia il turno di fabbrica) con il fatto storico di quando ogni operaio di fabbrica ha fatto il suo turno per iniziare il proprio turno in un particolare giorno. L'orologio è un vero momento, un vero punto nella sequenza temporale. Quindi lo registreremmo in una colonna di tipo TIMESTAMP WITH TIME ZONEanziché nel WITHOUTtipo.

Quindi, sì, ci sono casi d'uso legittimi per TIMESTAMP WITHOUT TIME ZONE. Ma nella mia esperienza con le app aziendali, sono relativamente rare. Negli affari, tendiamo a preoccuparci dei momenti concreti: quando è arrivata effettivamente la fattura, quando è entrato in vigore esattamente quel contratto, in quale momento è stata eseguita la transazione bancaria. Quindi in tali situazioni comuni, vogliamo il TIMESTAMP WITH TIME ZONEtipo.

Per ulteriori discussioni, vedere la mia risposta alla domanda simile, Devo memorizzare i timestamp UTC o l'ora locale per i turni

Postgres

Nota che Postgres non salva specificamente le informazioni sul fuso orario specificate quando si inserisce un timestamp.

  • TIMESTAMP WITH TIME ZONE
    • Qualsiasi fuso orario o offset specificato incluso nei dati di input viene utilizzato per regolare il valore su UTC e memorizzato. Le informazioni sulla zona / offset passate vengono quindi eliminate. Pensa a TIMESTAMP WITH TIME ZONEcome TIMESTAMP WITH RESPECT FOR TIME ZONE.
    • Un input di 12:00 mezzogiorno del 7 marzo di quest'anno in India avrà la sua ora del giorno regolata su UTC sottraendo cinque ore e mezza: 6:30 AM.
  • TIMESTAMP WITHOUT TIME ZONE
    • Qualsiasi fuso orario o offset specificato incluso nei dati di input viene completamente ignorato.
    • Un input di 12:00 mezzogiorno del 7 marzo di quest'anno in India è registrato come 12:00 il 7 marzo di quest'anno senza aggiustamento.

Lo standard SQL tocca a malapena problemi di tipo e comportamento dei dati data-ora. Quindi il database varia notevolmente nella gestione della data e dell'ora.


inoltre con i turni di fabbrica (o ospedalieri), chiunque lavori nel turno del cimitero nei giorni del passaggio all'ora legale avrà le proprie ore registrate in modo errato del suo registro senza fuso orario ..
Jasen,

Penso che ci sia un refuso nell'ultimo esempio: 'Un input di 12:00 mezzogiorno del 7 marzo .. dovrebbe essere' registrato come 12 : 00 '(non 21:00)
TmTron

11

Vorrei aggiungere un'altra visione a questo, che va contro gran parte di ciò che è stato scritto nelle altre risposte. Secondo me timestamp with time zoneha pochissimi casi d'uso validi e timestamp without time zone, in generale , dovrebbe essere preferito.

Innanzitutto, è necessario comprendere il modello "UTC ovunque", generalmente consigliato per tutte le applicazioni che non hanno requisiti molto speciali. Significa semplicemente che la tua applicazione dovrebbe rappresentare tutti i suoi timestamp in UTC, ovunque, sempre. Ovviamente, mostrerai la data / ora locale agli utenti, ma l'idea è di convertirli ai margini del tuo programma, durante il rendering della vista. Questo è il posto giusto per combinare il timestamp UTC (che potresti aver caricato da un database) e il fuso orario dell'utente (che potrebbe essere venuto dal browser) in un timestamp locale.

Se stai seguendo questo schema, allora timestamp with time zoneè un anti-schema. Tutto questo fa è fare in modo che PostgreSQL esegua conversioni del fuso orario durante la lettura e la scrittura di timestamp, in base alla TimeZonevariabile di sessione PostgreSQL . Invece di gestire i fusi orari ai limiti della tua applicazione, li hai introdotti nel suo cuore, nella stessa comunicazione con il tuo database. Devi aver cura di avere sempre PostgreSQL TimeZonecorrettamente configurato in ogni momento, aggiungendo un altro inutile punto di errore e confusione.

E per cosa? Se stai seguendo il modello UTC ovunque, la tua applicazione ha comunque solo timestamp UTC; quindi perché chiedere al database di fare conversioni sul fuso orario su di loro? Puoi semplicemente memorizzarli in una timestamp without time zonecolonna e trattarlo come se fosse sempre UTC. Nessuna conversione, nessun fuso orario, nessuna complicazione.


2
Penso che i sostenitori del timestamptz supportino anche il modello "UTC ovunque". È solo una regola che viene applicata a livello di database invece di fare affidamento solo sugli sviluppatori di app / API per applicarla? Se sei in grado di applicare questa pratica, perché no? Inoltre, puoi semplicemente imporre che tutte le connessioni postgres impostino il fuso orario su UTC. Anche se non lo fanno, il formato ISO conterrà l'offset tz. Quindi non è la stessa cosa di UTC ovunque ma applicata?
iamnat,

3
Innanzitutto, se il tuo fuso orario PostgreSQL è impostato su un valore diverso da UTC e stai utilizzando timestamptz, il tuo programma sta leggendo timestamp non UTC. Questo non è semplicemente il modello "UTC ovunque" e, a seconda della lingua del cliente, può o meno creare molte complicazioni. O sei UTC dappertutto, oppure stai utilizzando i timestamp locali ....
Shay Rojansky,

In secondo luogo, ancora una volta, se sei UTC ovunque nella tua applicazione, non c'è semplicemente alcun offset tz da inviare nel formato ISO per i tuoi timestamp. Le specifiche varieranno tra le lingue, ma idealmente dovresti usare un tipo di client che non è in grado di rappresentare qualsiasi cosa tranne un timestamp UTC (ad esempio un Instancein NodaTime / JodaTime). Stai praticamente descrivendo una situazione in cui "UTC ovunque" è quasi seguito, o un po 'seguito ...
Shay Rojansky,

Ancora una volta, è molto facile immaginare che una nuova istanza PostgreSQL sia configurata su alcuni server, conservando accidentalmente il fuso orario del computer locale configurato per impostazione predefinita. Le applicazioni leggono da questo server e ottengono timestamp locali in un fuso orario totalmente arbitrario (in cui si trova il server). Perché dovremmo desiderare questa ulteriore complicazione?
Shay Rojansky,

1
Potrebbe, ma poi avrebbe ancora meno senso usare timestamptz. L'intero punto di questo tipo è eseguire le conversioni del fuso orario come valori letti e scritti su PostgreSQL (internamente nel database, il timestamp viene sempre salvato come UTC). L'impostazione sempre del fuso orario della sessione su UTC disabilita effettivamente tali conversioni, quindi perché utilizzarle timestamptz? Detto in altro modo, se i valori nel database sono UTC e i valori che entrano ed escono dal database sono sempre UTC, allora perché avere consapevolezza del fuso orario nel tuo database?
Shay Rojansky,

2

Il datetimestamp inoltre non include le informazioni sul fuso orario, ma molte persone lo usano.

Certo, quello di per sé non è una risposta.

È valido per l'uso timestampe dateper tutti i timestamp e le date che si trovano sempre nello stesso fuso orario o che vengono memorizzati in relazione ad alcuni fusi orari noti.

Se il fuso orario è sempre lo stesso o implicito, allora è più antipattern memorizzarlo che non memorizzarlo (informazioni ridondanti).

I timestamp possono anche essere utilizzati per la memorizzazione di informazioni tecniche come quelle utilizzate nei registri delle applicazioni o per le misurazioni delle prestazioni. In questo caso, anche il fuso orario può essere irrilevante.


Al contrario, se si sta progettando o lavorando su un sistema distribuito o in qualsiasi sistema in cui parti del sistema saranno distribuite su diversi fusi orari, potrebbe essere considerato un anti-pattern da non utilizzare timestamp with timezone, sebbene alcuni sistemi potrebbero essere progettati per funzionare in un fuso orario, ad esempio UTC. In questo caso, la logica del fuso orario potrebbe essere inserita nel livello dell'applicazione, ma lo considero un anti-pattern, sì.


Capisco che in alcuni casi non fa male usare timestamp without timezone, ma mi compra mai qualcosa? Altrimenti, perché dovrei preoccuparmi se il timestamp with timezone datatipo è sempre uguale o più appropriato?
Marco Junius Bruto

Non archiviare informazioni ridondanti sarebbe il mio argomento principale. Presumo che l'aritmetica della data timestamp without timezonesarebbe anche più veloce, ma questo è probabilmente importante solo se stai elaborando miliardi di righe ...
Colin 't Hart,

1
@ Colin'tHart timestampe timestamptzsono entrambi memorizzati allo stesso modo. Non ci sono informazioni sul fuso orario memorizzate in a timestamptz, ma vengono invece convertite in UTC per l'archiviazione. Direi, usare sempre timestamptzquando i timestamp in questione indicano il tempo assoluto . Questo è tutto ciò che timestamptzsignifica. Ne ho scritto qui .
fphilipe,

2

Può sembrare allettante archiviare ed elaborare date / orari nell'ora locale se l'applicazione è limitata a un singolo fuso orario, ma ritengo che si tratti di un errore.

Quando si passa dall'ora legale all'ora solare viene ripetuta un'ora nell'ora locale (supponendo che la differenza sia di un'ora). Dove vivo in genere ciò accade intorno alle 2 del mattino, quindi l'ora locale è 01:58, 01:59, 01:00 e avanza solo fino alle 02:00 alla fine dell'ora ripetuta.

Se si tenta di ordinare gli eventi in base all'ora utilizzando l'ora locale, ciò significa che gli eventi di due ore distinte si mescolano e non compaiono nell'ordine in cui si sono effettivamente verificati.

In confronto UTC non ha questo problema e ordina in modo pulito. Pertanto, anche quando si lavora con un solo fuso orario, si desidera che il DB memorizzi ed elabori i tempi in UTC e li converta in / dall'ora locale per input / display. Questo è il comportamento di TIMESTAMP WITH TIME ZONE.

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.