it-swarm.it

Come posso ottenere l'attuale timestamp unix da PostgreSQL?

nix timestamp è il numero di secondi 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 questo non:

SELECT extract(Epoch from now() at time zone 'utc');

Vivo nel fuso orario UTC +02. Qual è il modo corretto per ottenere l'attuale timestamp unix da PostgreSQL?

Ciò restituisce l'ora 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
99
Jonas

In postgres, timestamp with time zone Può essere abbreviato come timestamptz e timestamp without time zone Come timestamp. Userò i nomi di tipo più brevi per semplicità.

Ottenere il timestamp Unix da un postgres timestamptz come now() è semplice, come dici tu, solo:

select extract(Epoch from now());

Questo è davvero 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 (o esplicitamente con at time zone O convertendo nel fuso orario della sessione) e le informazioni sul fuso orario vengono scartate . Non si riferisce più a un tempo assoluto. Questo è il motivo per cui di solito non si desidera memorizzare i timestamp come timestamp e normalmente si usa timestamptz - forse un film viene rilasciato alle 18:00 in una data particolare in ogni fuso orario , questo è il tipo di caso d'uso.

Se lavori sempre in un solo fuso orario potresti scappare con (mis) usando timestamp. La conversione in timestamptz è abbastanza intelligente da far fronte all'ora legale e si presume che i timestamp, ai fini della conversione, si trovino 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|
*/

DBFiddle

Tuttavia, nota 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|
*/

DBFiddle

Questo è perché :

PostgreSQL non esamina mai il contenuto di una stringa letterale prima di determinarne il tipo e pertanto tratterà entrambi […] come timestamp senza fuso orario. Per assicurarti che un valore letterale sia trattato come data/ora con fuso orario, dagli il tipo esplicito corretto ... In un valore letterale che è stato determinato come data/ora senza fuso orario, PostgreSQL ignorerà silenziosamente qualsiasi indicazione di fuso orario

SELECT extract(Epoch from now() at time zone 'utc');

non restituisce il timestamp corretto perché la conversione del fuso orario di postgres elimina le informazioni sul fuso orario dal risultato:

9.9.3. AT FUSO ORARIO

Sintassi: timestamp senza fuso orario AT FUSO ORARIO
Restituisce: timestamp con fuso orario
Tratta il timestamp dato senza fuso orario come si trova nel fuso orario specificato

Sintassi: timestamp con fuso orario AT FUSO ORARIO
Restituisce: timestamp senza fuso orario
Converti il ​​timestamp con il fuso orario nel nuovo fuso orario, senza designazione del fuso orario

successivamente, extract esamina il timestamp senza fuso orario e lo considera come un orario locale (anche se in realtà è già utc).

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)

Nell'ultima riga il primo at time zone esegue la conversione, il secondo assegna un nuovo fuso orario al risultato.

23
axil