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

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

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

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

Tím se vrátí správné časové razítko:

SELECT extract(epoch from now()); 

I když to není:

SELECT extract(epoch from now() at time zone "utc"); 

Žiji v časovém pásmu UTC +02. Jaký je správný způsob, jak získat aktuální časové razítko unixu 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 

Odpověď

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

Získání časového razítka Unix z postgres 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ávání absolutního času z čehokoli typu timestamptz, včetně now().

Věci se komplikují, pouze když máte pole timestamp .

Když do tohoto pole vložíte timestamptz data jako now(), budou 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 jsou zahozeny . Už neodkazuje na absolutní čas. Proto obvykle nechcete ukládat časová razítka jako timestamp a normálně byste použili timestamptz – možná bude film vydán v 18:00 na konkrétní datum v každém časovém pásmu , to je typ případu použití.

Pokud pracujete pouze v jednom časovém pásmu, můžete pomocí timestamp. Převod zpět na timestamptz je dostatečně chytrý, aby zvládl DST, a předpokládá se, že časová razítka jsou pro účely převodu 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

Mějte však na paměti 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 je proto, že :

PostgreSQL nikdy nezkoumá obsah doslovného řetězce před určením jeho typu, a proto bude s oběma […] zacházet jako s časovým razítkem bez časového pásma. zajistit, aby se s literálem zacházelo jako s časovým razítkem s časovým pásmem, dejte mu správný explicitní typ … V literálu, který byl určen jako časové razítko bez časového pásma, PostgreSQL tiše ignoruje jakékoli označení časového pásma. c5aa40c735 „>

Komentáře

  • Nějaký nápad, jak převést výsledné desetinné číslo na celé číslo bez desetinné čárky (myslím sloučení čísla a desetinné čárky jako jedno velké celé číslo). Díky.
  • Jako toto , ale ' si jistý, že to opravdu nechcete ' opravdu dělat. Možná chcete znásobit mocninu deseti a odstranit všechna zbývající desetinná místa?
  • @ W.M. Možná takhle? SELECT FLOOR(EXTRACT(epoch FROM NOW())*1000);

Odpověď

SELECT extract(epoch from now() at time zone "utc"); 

nevrací správné časové razítko, protože konverze časové zóny postgres vyhodí informace o časové zóně z výsledku:

9.9.3. V ČASOVÉ Zóně

Syntaxe: časové razítko bez časového pásma V ZÓNĚ ZÓNY
Vrátí: časové razítko s časovým pásmem
Zacházet s daným časovým razítkem bez časového pásma jako v zadaném časovém pásmu

Syntaxe: časové razítko s časovým pásmem V ČASOVÉ ZÓNĚ Zóna
Vrátí: časové razítko bez časového pásma
Převede 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ž ve skutečnosti už je utc).

Správný způsob by bylo:

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 provede první at time zone převod, seco Výsledek přiřadí nové časové pásmo.

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *