it-swarm-eu.dev

Jak získám aktuální unixové časové razítko z PostgreSQL?

nix timestamp je počet sekund od půlnoci UTC 1. ledna 1970.

Jak získám správné unixové časové razítko z PostgreSQL?

Při porovnání s currenttimestamp.com a timestamp.1e5b.de nedostávám očekávaný čas od PostgreSQL:

Vrací správné časové razítko:

SELECT extract(Epoch from now());

I když to tak není:

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

Bydlím v časové zóně UTC +02. Jaký je správný způsob, jak získat aktuální unixové časové razítko z PostgreSQL?

Tím se vrátí správné časové a časové pásmo:

SELECT now();
              now
-------------------------------
 2011-05-18 10:34:10.820464+02

Další srovnání:

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

V postgresu lze timestamp with time zone Zkrátit na timestamptz a timestamp without time zone Jako timestamp. Pro zjednodušení použiji kratší názvy typů.

Získání časového razítka Unix z postgresu timestamptz jako now() je jednoduché, jak říkáte, jen:

select extract(Epoch from now());

To je opravdu vše, co potřebujete vědět o získání absolutního času od všeho typu timestamptz, včetně now().

Věci se komplikují pouze tehdy, pokud máte pole timestamp.

Když do tohoto pole vložíte timestamptz data jako now(), bude nejprve převedena na konkrétní časové pásmo (buď explicitně s at time zone Nebo převedením na časové pásmo relace) a informace o časovém pásmu je zahozeno. Už to neznamená absolutní čas. To je důvod, proč obvykle nechcete ukládat časová razítka jako timestamp a obvykle byste měli používat timestamptz - možná se film dostane v 18 hodin k určitému datu v každém časovém pásmu, to je druh použití.

Pokud pracujete pouze v jednom časovém pásmu, můžete dostat (mis) pomocí timestamp. Převod zpět na timestamptz je dost chytrý, aby se vypořádal s DST, a časová razítka se pro účely převodu předpokládají v aktuálním časovém pásmu. Zde je příklad pro 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

Nezapomeňte však následující matoucí chování:

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

Toto protože :

PostgreSQL nikdy nezkoumá obsah doslovného řetězce před určením jeho typu, a proto bude považovat oba […] za časové razítko bez časového pásma. Chcete-li zajistit, aby se s literálem zacházelo jako s časovým razítkem s časovým pásmem, zadejte mu správný explicitní typ ... V literálu, který byl označen jako časové razítko bez časového pásma, PostgreSQL tiše ignoruje jakoukoli indikaci časového pásma

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

nevrátí správné časové razítko, protože konverze časového odstupu odhodí informace o časovém pásmu z výsledku:

9.9.3. AT ČASOVÁ ZÓNA

Syntaxe: časové razítko bez časového pásma AT TIME ZONE zone)
Vrací: časové razítko s časovým pásmem
Zacházejte s daným časovým razítkem bez časového pásma jako s umístěním v určeném časovém pásmu

Syntaxe: časové razítko s časovým pásmem AT ČASOVÁ ZÓNA zóna
Vrací: časové razítko bez časového pásma
Převést dané časové razítko s časovým pásmem na nové časové pásmo bez označení časového pásma

poté se extrakt podívá na časové razítko bez časového pásma a považuje jej za místní čas (i když je to již ve skutečnosti utc).

Správný způsob by byl:

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)

V posledním řádku první at time zone provede převod, druhý přiřadí k výsledku nové časové pásmo.

23
axil