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| */
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| */
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ásmuSyntaxe: č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.