nix-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 bekomme ich nicht die erwartete Zeit von PostgreSQL:
Dies gibt den richtigen Zeitstempel zurück:
SELECT extract(Epoch from now());
Während dies nicht:
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 zu erhalten?
Dies gibt die richtige Zeit und Zeitzone zurück:
SELECT now();
now
-------------------------------
2011-05-18 10:34:10.820464+02
Ein weiterer 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
In Postgres kann timestamp with time zone
Als timestamptz
und timestamp without time zone
Als timestamp
abgekürzt werden. Ich werde die kürzeren Typnamen der Einfachheit halber verwenden.
Das 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 timestamptz
zu erhalten, 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 . Es bezieht sich nicht mehr auf eine absolute Zeit. Aus diesem Grund möchten Sie Zeitstempel normalerweise nicht als timestamp
speichern und verwenden normalerweise timestamptz
- möglicherweise wird ein Film an einem bestimmten Datum um 18 Uhr veröffentlicht In jeder Zeitzone ist dies der Anwendungsfall.
Wenn Sie immer nur in einer einzigen Zeitzone arbeiten, können Sie mit timestamp
mit (mis) davonkommen. Die Konvertierung zurück 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|
*/
Dies liegt daran :
PostgreSQL untersucht niemals den Inhalt einer Literalzeichenfolge, bevor ihr 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 alle Zeitzonenangaben stillschweigend
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 AT TIME ZONE Zone
Rückgabe: Zeitstempel mit Zeitzone
Behandeln Sie den angegebenen Zeitstempel ohne Zeitzone als in der angegebenen Zeitzone befindlichSyntax: Zeitstempel mit Zeitzone AT TIME ZONE Zone
Rückgabe: Zeitstempel ohne Zeitzone
Konvertieren Sie einen bestimmten Zeitstempel mit Zeitzone in die neue Zeitzone ohne Zeitzonenbezeichnung
anschließend betrachtet 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 das erste at time zone
führt die Konvertierung durch, die zweite weist dem Ergebnis eine neue Zeitzone zu.