PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Darstellung einer zukünftigen Zeit in PostgreSQL

Es hört sich so an, als ob Sie eine Ortszeit speichern möchten in Bezug auf eine bestimmte Zeitzone. Speichern Sie in diesem Fall einen timestamp (ohne Zeitzone) und die timezone in einer separaten Spalte.

Angenommen, Sie möchten ein Ereignis aufzeichnen, das am 26. Februar 2030 um 10 Uhr in Chicago stattfindet, und es muss um 10 Uhr Ortszeit stattfinden unabhängig von der an diesem Datum geltenden Zeitzonenregel.

Wenn die Datenbank den Zeitstempel ohne Zeitzone speichert:

unutbu=# select '2030-02-26 10:00:00'::timestamp as localtime, 'America/Chicago' AS tzone;
+---------------------+-----------------+
|      localtime      |      tzone      |
+---------------------+-----------------+
| 2030-02-26 10:00:00 | America/Chicago |
+---------------------+-----------------+

Später können Sie die UTC-Datumszeit des Ereignisses mit

finden
unutbu=# select '2030-02-26 10:00:00'::timestamp AT TIME ZONE 'America/Chicago' AT TIME ZONE 'UTC';
+---------------------+
|      timezone       |
+---------------------+
| 2030-02-26 16:00:00 |
+---------------------+

Die Abfrage gibt die UTC-Datumszeit 2030-02-26 16:00:00 zurück , was 2030-02-26 10:00:00 entspricht Ortszeit in Chicago.

Verwenden Sie AT TIME ZONE verzögert die Anwendung der Zeitzonenregeln bis wann die Abfrage erfolgt statt wann der timestamptz wurde eingefügt.

Verwenden Sie AT TIME ZONE auf einem timestamp lokalisiert die Datumszeit in die angegebene Zeitzone, aber berichtet die Datumszeit in der Zeitzone des Benutzers .Mit AT TIME ZONE auf einem timestamptz konvertiert die Datumszeit in die angegebene Zeitzone, löscht dann den Offset und gibt so einen timestamp zurück .Oben, AT TIME ZONE wird zweimal verwendet:zuerst um einen timestamp zu lokalisieren und als nächstes den zurückgegebenen timestamptz konvertieren in eine neue Zeitzone (UTC). Das Ergebnis ist ein timestamp in UTC.

Hier ist ein Beispiel, das AT TIME ZONE demonstriert 's Verhalten bei timestamp s:

unutbu=# SET timezone = 'America/Chicago';
unutbu=# SELECT '2030-02-26 10:00:00'::timestamp AT TIME ZONE 'America/Chicago';
+------------------------+
|        timezone        |
+------------------------+
| 2030-02-26 10:00:00-06 |
+------------------------+

unutbu=# SET timezone = 'America/Los_Angeles';
unutbu=# SELECT '2030-02-26 10:00:00'::timestamp AT TIME ZONE 'America/Chicago';
+------------------------+
|        timezone        |
+------------------------+
| 2030-02-26 08:00:00-08 |
+------------------------+

2030-02-26 10:00:00-06 und 2030-02-26 08:00:00-08 sind die gleichen Datetimes, werden aber in unterschiedlichen Benutzerzeitzonen gemeldet. Dies zeigt, dass 10 Uhr in Chicago 8 Uhr in Los Angeles ist (unter Verwendung aktueller Zeitzonendefinitionen):

unutbu=# SELECT '2030-02-26 10:00:00-06'::timestamptz AT TIME ZONE 'America/Los_Angeles';
+---------------------+
|      timezone       |
+---------------------+
| 2030-02-26 08:00:00 |
+---------------------+

Eine Alternative zur Verwendung von AT TIME ZONE zweimal ist es, die Zeitzone des Benutzers festzulegen nach UTC . Dann könnten Sie

verwenden
select localtime AT TIME ZONE tzone

Beachten Sie, dass auf diese Weise ein timestamptz entsteht wird anstelle eines timestamp zurückgegeben .

Beachten Sie, dass das Speichern von Ortszeiten problematisch sein kann, da es nicht vorhandene Zeiten und mehrdeutige Zeiten geben kann. Beispiel:2018-03-11 02:30:00 ist eine nicht existierende Ortszeit in America/Chicago . Postgresql normalisiert nicht existierende Ortszeit, indem es annimmt, dass sie sich auf die entsprechende Zeit nach Beginn der Sommerzeit (DST) bezieht (als ob jemand vergessen hätte, seine Uhr vorzustellen):

unutbu=# select '2018-03-11 02:30:00'::timestamp AT TIME ZONE 'America/Chicago' AT TIME ZONE 'UTC';
+---------------------+
|      timezone       |
+---------------------+
| 2018-03-11 08:30:00 |
+---------------------+
(1 row)

unutbu=# select '2018-03-11 03:30:00'::timestamp AT TIME ZONE 'America/Chicago' AT TIME ZONE 'UTC';
+---------------------+
|      timezone       |
+---------------------+
| 2018-03-11 08:30:00 |
+---------------------+
(1 row)

Ein Beispiel für eine mehrdeutige Ortszeit ist 2018-11-04 01:00:00 in America/Chicago . Es tritt aufgrund der Sommerzeit zweimal auf. Postgresql löst diese Mehrdeutigkeit, indem es die spätere Zeit nach Ende der Sommerzeit wählt:

unutbu=# select '2018-11-04 01:00:00'::timestamp AT TIME ZONE 'America/Chicago' AT TIME ZONE 'UTC';
+---------------------+
|      timezone       |
+---------------------+
| 2018-11-04 07:00:00 |
+---------------------+

Beachten Sie, dass dies bedeutet, dass es keine Möglichkeit gibt, auf 2018-11-04 06:00:00 UTC zu verweisen durch Speicherung der Ortszeit in America/Chicago Zeitzone:

unutbu=# select '2018-11-04 00:59:59'::timestamp AT TIME ZONE 'America/Chicago' AT TIME ZONE 'UTC';
+---------------------+
|      timezone       |
+---------------------+
| 2018-11-04 05:59:59 |
+---------------------+