Unix-tidsstempel er antall sekunder siden midnatt UTC 1. januar 1970.
Hvordan får jeg riktig unix-tidsstempel fra PostgreSQL?
Når jeg sammenligner med currenttimestamp.com og tidsstempel.1e5b.de Jeg får ikke forventet tid fra PostgreSQL:
Dette returnerer riktig tidsstempel:
SELECT extract(epoch from now());
Selv om dette ikke gjør det:
SELECT extract(epoch from now() at time zone "utc");
Jeg bor i tidssonen UTC +02. Hva er den riktige måten å få den nåværende unix-tidsstemplet fra PostgreSQL?
Dette returnerer riktig tid og tidssone:
SELECT now(); now ------------------------------- 2011-05-18 10:34:10.820464+02
En annen sammenligning:
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
Svar
I postgres, timestamp with time zone
kan forkortes som timestamptz
, og timestamp without time zone
som timestamp
. Jeg vil bruke de kortere typenavnene for enkelhets skyld.
Å få Unix-tidsstempelet fra en postgres timestamptz
som now()
er enkelt, som du sier, bare:
select extract(epoch from now());
Det er egentlig alt du trenger å vite om å få absolutt tid fra noe av typen timestamptz
, inkludert now()
.
Ting blir bare kompliserte når du har et timestamp
-felt .
Når du setter timestamptz
data som now()
i det feltet, blir det først konvertert til en bestemt tidssone (enten eksplisitt med at time zone
eller ved å konvertere til øktens tidssone) og informasjon om tidssonen forkastes . Det refererer ikke lenger til en absolutt tid. Dette er grunnen til at du vil vanligvis ikke lagre tidsstempler som timestamp
og vil normalt bruke timestamptz
– kanskje en film blir utgitt kl 18.00 på en bestemt dato i hver tidssone , det er den slags brukssak.
Hvis du bare jobber i en enkelt tidssone, kan du komme unna med (mis) ved å bruke timestamp
. Konvertering tilbake til timestamptz
er smart nok til å takle sommertid, og tidsstemplene antas for konverteringsformål å være i gjeldende tidssone. Her er et eksempel for 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| */
Men vær oppmerksom på følgende forvirrende oppførsel:
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| */
Denne er fordi :
PostgreSQL undersøker aldri innholdet i en bokstavelig streng før den bestemmer typen, og vil derfor behandle begge […] som tidsstempel uten tidssone. sørg for at en bokstav blir behandlet som tidsstempel med tidssone, gi den riktig eksplisitt type … I en bokstav som er bestemt for å være tidstempel uten tidssone, vil PostgreSQL stille ignorere enhver tidssoneindikasjon
Kommentarer
- Enhver ide om hvordan du konverterer den resulterende desimalen til et helt tall uten desimaltegn (jeg mener å slå sammen tallet og desimalet som ett stort heltall). Takk.
- Som dette men jeg ' er sikker på at du ikke ' ikke vil gjøre det. Kanskje du vil multiplisere med en kraft på ti og fjerne eventuelle gjenværende desimaler?
- @ W.M. Kanskje slik?
SELECT FLOOR(EXTRACT(epoch FROM NOW())*1000);
Svar
SELECT extract(epoch from now() at time zone "utc");
returnerer ikke riktig tidsstempel fordi konvertering av tidssone fra postgres kaster bort tidssoneinformasjon fra resultatet:
9.9.3. PÅ TIDSSONE
Syntaks: tidsstempel uten tidssone PÅ TIDSZONE-sone
Returnerer: tidsstempel med tidssone
Behandle gitt tidsstempel uten tidssone som lokalisert i den angitte tidssonenSyntaks: tidsstempel med tidssone AT TIME ZONE zone
Returnerer: tidstempel uten tidssone
Konverter gitt tidsstempel med tidssone til den nye tidssonen, uten tidssonebetegnelse
etterpå, ser utdrag på tidsstempel uten tidssone og anser det for å være en lokal tid (selv om det allerede er utc faktisk).
Den riktige måten ville være:
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)
I siste linje utfører den første at time zone
konverteringen, seco og man tildeler resultatet en ny tidssone.