Utilizzando l'ora corrente in UTC come valore predefinito in PostgreSQL


172

Ho una colonna del TIMESTAMP WITHOUT TIME ZONEtipo e vorrei avere quel valore predefinito all'ora corrente in UTC. Ottenere l'ora corrente in UTC è facile:

postgres=# select now() at time zone 'utc';
          timezone          
----------------------------
 2013-05-17 12:52:51.337466
(1 row)

Come sta usando il timestamp corrente per una colonna:

postgres=# create temporary table test(id int, ts timestamp without time zone default current_timestamp);
CREATE TABLE
postgres=# insert into test values (1) returning ts;
             ts             
----------------------------
 2013-05-17 14:54:33.072725
(1 row)

Ma questo utilizza l'ora locale. Il tentativo di forzarlo su UTC provoca un errore di sintassi:

postgres=# create temporary table test(id int, ts timestamp without time zone default now() at time zone 'utc');
ERROR:  syntax error at or near "at"
LINE 1: ...int, ts timestamp without time zone default now() at time zo...

Risposte:


297

Non è nemmeno necessaria una funzione. Metti solo le parentesi attorno all'espressione predefinita:

create temporary table test(
    id int, 
    ts timestamp without time zone default (now() at time zone 'utc')
);

2
Riesco a vedere una funzione come now_utc () brilla davvero quando si scrivono query
misaxi

Funziona anche quando l'ora torna indietro di un'ora - now () restituisce un timestamp che conosce l'offset da UTC.
Clay Lenhart,

1
FWIW, l'esecuzione di questo query in PostgreSQL 11.5: ALTER TABLE testcase_result ADD COLUMN date_created TIMESTAMP WITHOUT TIME ZONE DEFAULT (NOW() AT TIME ZONE "UTC") NOT NULL;fallisce con: ERROR: column "UTC" does not exist. Assicurati che 'utc'sia tutto minuscolo.
code_dredd,

2
Correzione: anche la 'utc'stringa deve essere racchiusa tra virgolette singole, non tra virgolette doppie.
code_dredd,

56

Ancora un'altra soluzione:

timezone('utc', now())

26

Avvolgilo in una funzione:

create function now_utc() returns timestamp as $$
  select now() at time zone 'utc';
$$ language sql;

create temporary table test(
  id int,
  ts timestamp without time zone default now_utc()
);

16

Che dire

now()::timestamp

Se l'altro timestamp è senza fuso orario, questo cast produrrà il tipo corrispondente "timestamp senza fuso orario" per l'ora corrente.

Vorrei leggere quello che gli altri pensano di quell'opzione, però. Non mi fido ancora della mia comprensione di questo "con / senza" fuso orario.

EDIT: aggiungendo il commento di Michael Ekoka qui perché chiarisce un punto importante:

Avvertimento. La domanda riguarda la generazione del timestamp predefinito in UTC per una colonna timestamp che non memorizza il fuso orario (forse perché non è necessario memorizzare il fuso orario se si sa che tutti i timestamp condividono lo stesso). Ciò che fa la tua soluzione è generare un timestamp locale (che per la maggior parte delle persone non sarà necessariamente impostato su UTC) e memorizzarlo come un timestamp ingenuo (uno che non specifica il suo fuso orario).


È un trucco interessante ma può creare confusione a meno che tu non sia consapevole di questo comportamento. La risposta accettata è cristallina sull'azione e sul risultato desiderati. Lo stesso vale per la funzione, ma resto lontano dalle funzioni nei DB ....
Frank V,

nella mia opzione genera datetime locale in db
VelikiiNehochuha,

Avvertimento. La domanda riguarda la generazione del timestamp predefinito in UTC per una colonna timestamp che non memorizza il fuso orario (forse perché non è necessario memorizzare il fuso orario se si sa che tutti i timestamp condividono lo stesso). Ciò che fa la tua soluzione è generare un timestamp locale (che per la maggior parte delle persone non sarà necessariamente impostato su UTC) e memorizzarlo come un timestamp ingenuo (uno che non specifica il suo fuso orario).
Michael Ekoka,

@MichaelEkoka Ho aggiunto il tuo commento alla risposta - per favore vai avanti e modificalo se vuoi. Lo stai spiegando molto chiaramente. Grazie!
Risadinha,

Avvertenza : un timestamp con campo fuso orario NON memorizza il fuso orario, contrariamente a un'ipotesi ragionevole. Vedi il link sotto e cerca la pagina per UTC. All'ingresso, un timestamp con fuso orario converte il valore in entrata in utc e memorizza quel valore SENZA FUSO ORARIO O INFORMAZIONI OFFSET . All'uscita, il valore utc memorizzato viene convertito in un'ora locale utilizzando il fuso orario del client, se disponibile. Questo tipo riguarda la conversione del valore al momento della query. Dovresti testarlo memorizzando da un fuso orario e selezionando da un altro. postgresql.org/docs/11/datatype-datetime.html
Tom

7

Queste sono 2 soluzioni equivalenti:

(nel codice seguente, si dovrebbe sostituire 'UTC'per zona e now()per timestamp )

  1. timestamp AT TIME ZONE zone - Conforme agli standard SQL
  2. timezone(zone, timestamp) - probabilmente più leggibile

Il fuso orario della funzione (zona, data / ora) è equivalente alla zona data / ora del costrutto conforme a SQL AT TIME ZONE.


Spiegazione:

  • il fuso orario può essere specificato come stringa di testo (ad es. 'UTC') o come intervallo (ad es. INTERVAL '-08:00'): ecco un elenco di tutti i fusi orari disponibili
  • timestamp può essere qualsiasi valore di tipo timestamp
  • now()restituisce un valore di tipo timestamp (proprio quello che ci serve) con il fuso orario predefinito del database collegato (ad esempio 2018-11-11T12:07:22.3+05:00).
  • timezone('UTC', now())trasforma l'ora corrente (di tipo timestamp con fuso orario ) nell'equivalente timezonless in UTC.
    Ad esempio, SELECT timestamp with time zone '2020-03-16 15:00:00-05' AT TIME ZONE 'UTC'tornerà 2020-03-16T20:00:00Z.

Documenti: fuso orario ()


1
Grazie per aver riassunto queste cose. Ho usato la versione minuscola at timezone 'utc'e questo non ha funzionato con la mia installazione PostgreSQL. Risolto problema con le lettere maiuscole
Geradlus_RU

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.