Unix-Zeitstempel ist die Anzahl der Sekunden seit Mitternacht UTC am 1. Januar 1970.
Wie erhalte ich den richtigen Unix-Zeitstempel von PostgreSQL?
Beim Vergleich mit currenttimestamp.com und timestamp.1e5b.de Ich erhalte nicht die erwartete Zeit von PostgreSQL:
Dies gibt den korrekten Zeitstempel zurück:
SELECT extract(epoch from now());
Während dies nicht der Fall ist:
SELECT extract(epoch from now() at time zone "utc");
Ich lebe in der Zeitzone UTC +02. Was ist der richtige Weg, um den aktuellen Unix-Zeitstempel von PostgreSQL abzurufen?
Dies gibt die richtige Zeit und Zeitzone zurück:
SELECT now(); now ------------------------------- 2011-05-18 10:34:10.820464+02
Ein anderer Vergleich:
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
Antwort
In postgres timestamp with time zone
kann als timestamptz
und timestamp without time zone
als timestamp
abgekürzt werden. Ich werde der Einfachheit halber die kürzeren Typnamen verwenden.
Abrufen des Unix-Zeitstempels von einem Postgres timestamptz
wie now()
ist Einfach, wie Sie sagen, nur:
select extract(epoch from now());
Das ist wirklich alles, was Sie wissen müssen, um die absolute Zeit von irgendetwas vom Typ , einschließlich now()
.
Die Dinge werden nur kompliziert, wenn Sie ein timestamp
-Feld haben .
Wenn Sie timestamptz
Daten wie now()
in dieses Feld einfügen, werden diese zuerst in eine bestimmte Zeitzone konvertiert (entweder explizit mit at time zone
oder durch Konvertieren in die Sitzungszeitzone) und die Zeitzoneninformationen werden verworfen . Sie beziehen sich nicht mehr auf eine absolute Zeit. Aus diesem Grund Normalerweise möchten Sie Zeitstempel nicht als timestamp
speichern und verwenden normalerweise timestamptz
– möglicherweise wird ein Film zu einem bestimmten Zeitpunkt um 18 Uhr veröffentlicht Datum in jeder Zeitzone , das ist die Art von Anwendungsfall.
Wenn Sie immer nur in einer einzigen Zeitzone arbeiten, können Sie mit timestamp
. Die Rückkonvertierung nach timestamptz
ist clever genug, um mit der Sommerzeit fertig zu werden, und es wird angenommen, dass sich die Zeitstempel für Konvertierungszwecke in der aktuellen Zeitzone befinden. 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| */
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| */
Diese ist darauf zurückzuführen, dass :
PostgreSQL untersucht niemals den Inhalt einer Literalzeichenfolge, bevor ihr Typ bestimmt wird, und behandelt daher beide […] als Zeitstempel ohne Zeitzone Stellen Sie sicher, dass ein Literal als Zeitstempel mit Zeitzone behandelt wird, und geben Sie ihm den richtigen expliziten Typ. In einem Literal, das als Zeitstempel ohne Zeitzone festgelegt wurde, ignoriert PostgreSQL stillschweigend alle Zeitzonenangaben.
Kommentare
- Jede Idee, wie die resultierende Dezimalstelle in eine Ganzzahl ohne Dezimalpunkt konvertiert werden kann (ich meine das Zusammenführen der Zahl und der Dezimalstelle als eine große ganze Zahl). Danke.
- Wie dies , aber ich ' bin sicher, dass Sie ' das nicht wirklich wollen. Vielleicht möchten Sie mit einer Zehnerpotenz multiplizieren und alle verbleibenden Dezimalstellen entfernen?
- @ W.M. Vielleicht so?
SELECT FLOOR(EXTRACT(epoch FROM NOW())*1000);
Antwort
SELECT extract(epoch from now() at time zone "utc");
gibt nicht den richtigen Zeitstempel zurück, da die Postzonen-Zeitzonenkonvertierung Zeitzoneninformationen aus dem Ergebnis entfernt:
9.9.3. AT TIME ZONE
Syntax: Zeitstempel ohne Zeitzone ZEITZONE Zone
Rückgabe: Zeitstempel mit Zeitzone
Behandeln Sie den angegebenen Zeitstempel ohne Zeitzone als in der angegebenen ZeitzoneSyntax: Zeitstempel mit Zeitzone AT TIME ZONE Zone
Rückgabe: Zeitstempel ohne Zeitzone
Konvertieren Sie den angegebenen Zeitstempel mit Zeitzone in die neue Zeitzone ohne Zeitzonenbezeichnung
Anschließend betrachtet der Extrakt den Zeitstempel ohne Zeitzone und betrachtet ihn als Ortszeit (obwohl er tatsächlich bereits utc ist).
Der richtige Weg wä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)
In der letzten Zeile führt die erste at time zone
die Konvertierung durch, die seco Und man weist dem Ergebnis eine neue Zeitzone zu.