Risposte:
Le differenze sono trattate nella documentazione di PostgreSQL per i tipi di data / ora . Sì, il trattamento TIMEo TIMESTAMPdifferisce tra uno WITH TIME ZONEo WITHOUT TIME ZONE. Non influisce sulla modalità di memorizzazione dei valori; influenza il modo in cui vengono interpretati.
Gli effetti dei fusi orari su questi tipi di dati sono trattati in modo specifico nei documenti. La differenza deriva da ciò che il sistema può ragionevolmente sapere sul valore:
Con un fuso orario come parte del valore, il valore può essere visualizzato come ora locale nel client.
Senza un fuso orario come parte del valore, il fuso orario predefinito ovvio è UTC, quindi viene visualizzato per quel fuso orario.
Il comportamento differisce in base ad almeno tre fattori:
WITH TIME ZONEo WITHOUT TIME ZONE) del valore.Ecco alcuni esempi che coprono le combinazioni di tali fattori:
foo=> SET TIMEZONE TO 'Japan';
SET
foo=> SELECT '2011-01-01 00:00:00'::TIMESTAMP;
timestamp
---------------------
2011-01-01 00:00:00
(1 row)
foo=> SELECT '2011-01-01 00:00:00'::TIMESTAMP WITH TIME ZONE;
timestamptz
------------------------
2011-01-01 00:00:00+09
(1 row)
foo=> SELECT '2011-01-01 00:00:00+03'::TIMESTAMP;
timestamp
---------------------
2011-01-01 00:00:00
(1 row)
foo=> SELECT '2011-01-01 00:00:00+03'::TIMESTAMP WITH TIME ZONE;
timestamptz
------------------------
2011-01-01 06:00:00+09
(1 row)
foo=> SET TIMEZONE TO 'Australia/Melbourne';
SET
foo=> SELECT '2011-01-01 00:00:00'::TIMESTAMP;
timestamp
---------------------
2011-01-01 00:00:00
(1 row)
foo=> SELECT '2011-01-01 00:00:00'::TIMESTAMP WITH TIME ZONE;
timestamptz
------------------------
2011-01-01 00:00:00+11
(1 row)
foo=> SELECT '2011-01-01 00:00:00+03'::TIMESTAMP;
timestamp
---------------------
2011-01-01 00:00:00
(1 row)
foo=> SELECT '2011-01-01 00:00:00+03'::TIMESTAMP WITH TIME ZONE;
timestamptz
------------------------
2011-01-01 08:00:00+11
(1 row)
timestamp with time zonee timestamp without time zone, in Postgres * non memorizzano effettivamente le informazioni sul fuso orario. Puoi confermarlo con uno sguardo alla pagina doc del tipo di dati: Entrambi i tipi occupano lo stesso numero di ottetti e hanno l'intervallo di valori di salvataggio, quindi non c'è spazio per la memorizzazione delle informazioni sul fuso orario. Il testo della pagina lo conferma. Qualcosa di un termine improprio: "senza tz" significa "ignora offset durante l'inserimento dei dati" e "con tz" significa "usa offset per adattarsi a UTC".
Cerco di spiegarlo in modo più comprensibile della documentazione PostgreSQL citata.
Nessuna delle due TIMESTAMPvarianti memorizza un fuso orario (o un offset), nonostante ciò che suggeriscono i nomi. La differenza sta nell'interpretazione dei dati memorizzati (e nell'applicazione prevista), non nel formato di archiviazione stesso:
TIMESTAMP WITHOUT TIME ZONEmemorizza la data e l'ora locale (ovvero la data del calendario da parete e l'ora dell'orologio da parete). Il suo fuso orario non è specificato da quanto PostgreSQL può dire (sebbene l'applicazione possa sapere di cosa si tratta). Pertanto, PostgreSQL non esegue alcuna conversione relativa al fuso orario su input o output. Se il valore è stato inserito nel database come '2011-07-01 06:30:30', quindi nessun mater in quale fuso orario lo visualizzi in seguito, continuerà a dire anno 2011, mese 07, giorno 01, 06 ore, 30 minuti e 30 secondi (in un formato). Inoltre, qualsiasi scostamento o il fuso orario specificato nella ingresso viene ignorato da PostgreSQL, così '2011-07-01 06:30:30+00'e '2011-07-01 06:30:30+05'sono gli stessi solo '2011-07-01 06:30:30'. Per gli sviluppatori Java: è analogo a java.time.LocalDateTime.
TIMESTAMP WITH TIME ZONEmemorizza un punto sulla linea temporale UTC. Come appare (quante ore, minuti, ecc.) Dipende dal tuo fuso orario, ma si riferisce sempre allo stesso istante "fisico" (come il momento di un evento fisico reale). L'input viene convertito internamente in UTC, ed è così che viene memorizzato. Per questo, l'offset dell'ingresso deve essere noto, quindi quando l'ingresso non contiene offset o fuso orario espliciti (come '2011-07-01 06:30:30'), si presume che si trovi nel fuso orario corrente della sessione PostgreSQL, altrimenti viene utilizzato l'offset o il fuso orario specificati in modo esplicito (come in '2011-07-01 06:30:30+05'). L'output viene visualizzato convertito nel fuso orario corrente della sessione PostgreSQL. Per gli sviluppatori Java: è analogo a java.time.Instant(con una risoluzione inferiore), ma con JDBC e JPA 2.2 dovresti mapparlo su java.time.OffsetDateTime(o su java.util.Dateojava.sql.Timestamp ovviamente).
Alcuni sostengono che entrambe le TIMESTAMPvarianti memorizzano la data e l'ora UTC. Un po ', ma secondo me è confuso. TIMESTAMP WITHOUT TIME ZONEè memorizzato come un TIMESTAMP WITH TIME ZONE, che viene visualizzato con il fuso orario UTC sembra dare lo stesso anno, mese, giorno, ore, minuti, secondi e microsecondi come sono nella data-ora locale. Ma non ha lo scopo di rappresentare il punto sulla linea temporale che dice l'interpretazione UTC, è solo il modo in cui sono codificati i campi data-ora locali. (È un gruppo di punti sulla linea del tempo, poiché il fuso orario reale non è UTC; non sappiamo di cosa si tratti.)
TIMESTAMP WITH TIME ZONEcome a Instant. Entrambi rappresentano un punto della sequenza temporale in UTC. Instantè preferito, a mio avviso, rispetto a OffsetDateTimecome è più autocompattante: A TIMESTAMP WITH TIME ZONEviene sempre recuperato dal database come UTC e un Instantè sempre in UTC quindi una corrispondenza naturale, mentre OffsetDateTimepuò portare altri offset.
OffsetDateTimeil tipo Java mappato. Non sono sicuro che Instancesia ancora supportato ufficiosamente da qualche parte.
'2011-07-01 06:30:30+00'ed '2011-07-01 06:30:30+05' è ignorato ma sono in grado di farlo insert into test_table (date) values ('2018-03-24T00:00:00-05:00'::timestamptz);e lo convertirà in utc correttamente. dove la data è data e ora senza fuso orario. Sto cercando di capire quale sia il valore principale del timestamp con il fuso orario e di avere problemi.
::timestamptz. Con ciò si converte la stringa in TIMESTAMP WITH TIME ZONE, e quando verrà ulteriormente convertita in WITHOUT TIME ZONE, che memorizzerà il "calendario da parete" giorno e l'ora dell'orologio da parete di quell'istante, come si vede dal fuso orario della sessione (che è forse UTC). Sarà comunque solo un timestamp locale con offset non specificato (nessuna zona).
Ecco un esempio che dovrebbe aiutare. Se si dispone di un timestamp con un fuso orario, è possibile convertire tale timestamp in qualsiasi altro fuso orario. Se non hai un fuso orario di base, questo non verrà convertito correttamente.
SELECT now(),
now()::timestamp,
now() AT TIME ZONE 'CST',
now()::timestamp AT TIME ZONE 'CST'
Produzione:
-[ RECORD 1 ]---------------------------
now | 2018-09-15 17:01:36.399357+03
now | 2018-09-15 17:01:36.399357
timezone | 2018-09-15 08:01:36.399357
timezone | 2018-09-16 02:01:36.399357+03
timestampe cosa timestamptzsignifichi. timestamptzindica un punto assoluto nel tempo (UTC) mentre timestampindica ciò che l'orologio ha mostrato in un determinato fuso orario. Quindi, quando ti converti timestamptzin un fuso orario ti chiedi cosa ha mostrato l'orologio a New York in questo preciso momento? mentre quando "converti" a timestamp, ti stai chiedendo qual è stato il momento assoluto in cui l'orologio di New York ha mostrato x?
AT TIME ZONEcostrutto è un rompicapo, anche se hai già capito i tipi WITHvs. WITHOUT TIME ZONEQuindi è una scelta curiosa per spiegarli. (: ( AT TIME ZONEconverte un WITH TIME ZONEtimestamp in un WITHOUT TIME ZONEtimestamp, e viceversa ... non esattamente ovvio.)
now()::timestamp AT TIME ZONE 'CST'non ha senso, a meno che tu non sappia in quale istante un orologio per la zona 'CST' mostrerebbe l'ora che il tuo orologio locale sta attualmente mostrando