In postgres timestamp with time zone
kann als timestamptz
und timestamp without time zone
als abgekürzt werden timestamp
. Ich werde der Einfachheit halber die kürzeren Typnamen verwenden.
Erster den Unix - Zeitstempel von einem Postgres timestamptz
wie now()
einfach ist, wie Sie sagen, nur:
select extract(epoch from now());
Das ist wirklich alles, was Sie wissen müssen, um die absolute Zeit von jedem Typ zu erhalten timestamptz
, einschließlich now()
.
Kompliziert wird es erst, wenn man ein timestamp
Feld hat.
Wenn Sie timestamptz
Daten wie diese now()
in dieses Feld einfügen, werden sie zuerst in eine bestimmte Zeitzone konvertiert (entweder explizit mit at time zone
oder durch Konvertieren in die Sitzungszeitzone) und die Zeitzoneninformationen werden verworfen . Es bezieht sich nicht mehr auf eine absolute Zeit. Aus diesem Grund möchten Sie Zeitstempel timestamp
normalerweise nicht so speichern, wie sie normalerweise verwendet werden timestamptz
- möglicherweise wird ein Film um 18:00 Uhr an einem bestimmten Datum in jeder Zeitzone veröffentlicht. Dies ist die Art von Anwendungsfall.
Wenn Sie immer nur in einer einzigen Zeitzone arbeiten, können Sie (Fehl-) Gebrauch machen timestamp
. Die Konvertierung zurück nach timestamptz
ist klug genug, um mit der Sommerzeit fertig zu werden, und für Konvertierungszwecke wird angenommen, dass die Zeitstempel in der aktuellen Zeitzone liegen. Hier ist ein Beispiel für 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
Beachten Sie jedoch das folgende verwirrende Verhalten:
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
Das liegt daran, dass :
PostgreSQL untersucht niemals den Inhalt eines Literalstrings, bevor sein Typ bestimmt wird, und behandelt daher beide […] als Zeitstempel ohne Zeitzone. Um sicherzustellen, dass ein Literal als Zeitstempel mit Zeitzone behandelt wird, geben Sie ihm den richtigen expliziten Typ ... In einem Literal, das als Zeitstempel ohne Zeitzone festgelegt wurde, ignoriert PostgreSQL jede Zeitzonenangabe unbemerkt
SELECT FLOOR(EXTRACT(epoch FROM NOW())*1000);
gibt nicht den korrekten Zeitstempel zurück, da nach der Konvertierung der Zeitzone die Zeitzoneninformationen aus dem Ergebnis entfernt werden:
Anschließend betrachtet extract den Zeitstempel ohne Zeitzone und betrachtet ihn als Ortszeit (obwohl dies bereits utc ist).
Der richtige Weg wäre:
In der letzten Zeile führt die erste
at time zone
die Konvertierung durch, die zweite ordnet dem Ergebnis eine neue Zeitzone zu.quelle