Unix timestamp è il numero di secondi trascorsi dalla mezzanotte UTC del 1 gennaio 1970.
Come posso ottenere il timestamp unix corretto da PostgreSQL?
Quando si confronta con currenttimestamp.com e timestamp.1e5b.de Non ottengo il tempo previsto da PostgreSQL:
Questo restituisce il timestamp corretto:
SELECT extract(epoch from now());
Anche se non “t:
SELECT extract(epoch from now() at time zone "utc");
Vivo nel fuso orario UTC +02. Qual è il modo corretto per ottenere il timestamp unix corrente da PostgreSQL?
Questo restituisce lora e il fuso orario corretti:
SELECT now(); now ------------------------------- 2011-05-18 10:34:10.820464+02
Un altro confronto:
select now(), extract(epoch from now()), extract(epoch from now() at time zone "utc"); now | date_part | date_part -------------------------------+------------------+------------------ 2011-05-18 10:38:16.439332+02 | 1305707896.43933 | 1305700696.43933 (1 row) Unix timestamp from the web sites: 1305707967
Risposta
In postgres, timestamp with time zone
può essere abbreviato come timestamptz
e timestamp without time zone
come timestamp
. Userò nomi di tipo più brevi per semplicità.
Ottenere il timestamp di Unix da un timestamptz
come now()
è semplice, come dici tu, semplicemente:
select extract(epoch from now());
Questo è tutto ciò che devi sapere per ottenere il tempo assoluto da qualsiasi cosa di tipo timestamptz
, incluso now()
.
Le cose si complicano solo quando hai un campo timestamp
.
Quando inserisci timestamptz
dati come now()
in quel campo, verranno prima convertiti in un particolare fuso orario (esplicitamente con at time zone
o convertendolo nel fuso orario della sessione) e le informazioni sul fuso orario vengono eliminate . Non si riferiscono più a unora assoluta. Questo è il motivo per cui di solito non vuoi memorizzare i timestamp come timestamp
e normalmente utilizzeresti timestamptz
– forse un film esce alle 18:00 su un determinato data in ogni fuso orario , questo è il tipo di caso duso.
Se lavori solo in un unico fuso orario potresti farla franca (male) usando timestamp
. La riconversione a timestamptz
è abbastanza intelligente da far fronte allora legale e, ai fini della conversione, si presume che i timestamp siano nel fuso orario corrente. Ecco un esempio per GMT / BST:
select "2011-03-27 00:59:00.0+00"::timestamptz::timestamp::timestamptz , "2011-03-27 01:00:00.0+00"::timestamptz::timestamp::timestamptz; /* |timestamptz |timestamptz | |:---------------------|:---------------------| |2011-03-27 00:59:00+00|2011-03-27 02:00:00+01| */
Tuttavia, tieni presente il seguente comportamento confuso:
set timezone to 0; values(1, "1970-01-01 00:00:00+00"::timestamp::timestamptz) , (2, "1970-01-01 00:00:00+02"::timestamp::timestamptz); /* |column1|column2 | |------:|:---------------------| | 1|1970-01-01 00:00:00+00| | 2|1970-01-01 00:00:00+00| */
Questo è perché :
PostgreSQL non esamina mai il contenuto di una stringa letterale prima di determinarne il tipo, e quindi tratterà entrambi […] come timestamp senza fuso orario. assicurati che un letterale sia trattato come timestamp con fuso orario, dagli il tipo esplicito corretto … In un letterale che è stato determinato come timestamp senza fuso orario, PostgreSQL ignorerà silenziosamente qualsiasi indicazione di fuso orario
Commenti
- Qualche idea su come convertire il decimale risultante in un intero senza punto decimale (intendo unire il numero e il decimale come un intero grande). Grazie.
- Come questo ma ' sono sicuro che ' non lo desideri veramente. Forse vuoi moltiplicare per una potenza di dieci e togliere i decimali rimanenti?
- @ W.M. Forse così?
SELECT FLOOR(EXTRACT(epoch FROM NOW())*1000);
Risposta
SELECT extract(epoch from now() at time zone "utc");
non restituisce il timestamp corretto perché la conversione del fuso orario postgres elimina le informazioni sul fuso orario dal risultato:
9.9.3. AL FUSO ORARIO
Sintassi: timestamp senza fuso orario AT TIME ZONE zone
Restituisce: timestamp con fuso orario
Tratta data timestamp senza fuso orario come situato nel fuso orario specificatoSintassi: timestamp con fuso orario AT TIME ZONE zone
Restituisce: timestamp senza fuso orario
Converte data timestamp con fuso orario nel nuovo fuso orario, senza designazione di fuso orario
in seguito, lestrazione guarda il timestamp senza fuso orario e considera lora locale (sebbene sia già utc in effetti).
Il modo corretto sarebbe:
select now(), extract(epoch from now()), -- correct extract(epoch from now() at time zone "utc"), -- incorrect extract(epoch from now() at time zone "utc" at time zone "utc"); -- correct now | date_part | date_part | date_part -------------------------------+------------------+------------------+------------------ 2014-10-14 10:19:23.726908+02 | 1413274763.72691 | 1413267563.72691 | 1413274763.72691 (1 row)
Nellultima riga il primo at time zone
esegue la conversione, il seco nd si assegna un nuovo fuso orario al risultato.