it-swarm.com.de

PostgreSQL-Datum () mit Zeitzone

Ich habe ein Problem beim Auswählen von Datumsangaben in Postgres - sie werden in UTC gespeichert, aber nicht ordnungsgemäß mit der Funktion Date () konvertiert.

Das Konvertieren des Zeitstempels in ein Datum gibt mir das falsche Datum, wenn es nach 16 Uhr PST ist.

2012-06-21 sollte sein 2012-06-20 in diesem Fall.

Das starts_at Spaltendatentyp ist timestamp without time zone. Hier sind meine Fragen:

Ohne Konvertierung in die PST-Zeitzone:

Select starts_at from schedules where id = 40;

      starts_at      
---------------------
 2012-06-21 01:00:00

Das Konvertieren ergibt folgendes:

Select (starts_at at time zone 'pst') from schedules where id = 40;
        timezone        
------------------------
 2012-06-21 02:00:00-07

Aber weder auf das richtige Datum in der Zeitzone konvertieren.

42
Matthew Lehner

Ich sehe den genauen Typ von starts_at In Ihrer Frage nicht. Sie sollten diese Informationen wirklich angeben, sie sind der Schlüssel zur Lösung. Ich muss raten.

Grundsätzlich speichert PostgreSQL always den UTC-Zeitwert für den Typ timestamp with time zone Intern. Nur die Anzeige variiert mit Ihrer aktuellen Einstellung timezone. Die Wirkung des Konstrukts AT TIME ZONE ändert sich auch mit dem zugrunde liegenden Datentyp. Mehr Details:

Wenn Sie ein date vom Typ timestamp [without time zone] extrahieren, erhalten Sie das Datum für die aktuelle Zeitzone. Der Tag in der Ausgabe ist der gleiche wie in der Anzeige des Wertes timestamp.

Wenn Sie ein date vom Typ timestamp with time zone (kurz timestamptz) extrahieren, wird zuerst der Zeitzonenversatz "angewendet". Sie erhalten weiterhin das Datum für die aktuelle Zeitzone, das mit der Anzeige des Zeitstempels übereinstimmt. Der gleiche Zeitpunkt gilt für den nächsten Tag in Teilen Europas, wenn es nach 16 Uhr ist. in Kalifornien zum Beispiel. Um das Datum für eine bestimmte Zeitzone zu erhalten, wenden Sie zuerst AT TIME ZONE An.

Daher widerspricht das, was Sie oben in der Frage beschreiben, Ihrem Beispiel.

Vorausgesetzt, starts_at Ist ein timestamp [without time zone] und die Zeit auf Ihrem Server ist auf die lokale Zeit eingestellt. Testen Sie mit:

SELECT now();

Zeigt es die gleiche Zeit wie eine Uhr an Ihrer Wand an? Wenn ja (und der Datenbankserver mit der richtigen Zeit ausgeführt wird), stimmt die Einstellung von timezone Ihrer aktuellen Sitzung mit Ihrer lokalen Zeitzone überein. Wenn nicht, können Sie die Einstellung von timezone in Ihrem postgresql.conf Oder Ihrem Client für die Sitzung aufrufen. Details im Handbuch.

Beachten Sie, dass der Versatz timezone das entgegengesetzte Zeichen verwendet, das in Zeitstempel-Literalen angezeigt wird. Sehen:

Um Ihr lokales Datum zu erhalten, geben Sie einfach starts_at Ein

SELECT starts_at::date

Gleichbedeutend mit:

SELECT date(starts_at)

Übrigens, Ihre Ortszeit ist momentan bei UTC-7, nicht bei UTC-8, da die Sommerzeit in Kraft ist (nicht unter den helleren Ideen der Menschheit).

Die Pacific Standard TIME (PST) ist normalerweise 8 Stunden "früher" (größerer timestamp Wert) als die UTC (Universal Time Zone), aber während der Sommerzeit (wie jetzt) ​​können es 7 Stunden sein. Deshalb wird in Ihrem Beispiel timestamptz als 2012-06-21 02:00:00-07 angezeigt. Das Konstrukt AT TIME ZONE 'PST' Berücksichtigt die Sommerzeit. Diese beiden Ausdrücke führen zu unterschiedlichen Ergebnissen (einer im Winter, einer im Sommer) und können bei der Besetzung zu unterschiedlichen Daten führen:

SELECT '2012-06-21 01:00:00'::timestamp AT TIME ZONE 'PST'
     , '2012-12-21 01:00:00'::timestamp AT TIME ZONE 'PST'
31

Grundsätzlich ist was Sie wollen:

$ select starts_at AT TIME ZONE 'UTC' AT TIME ZONE 'US/Pacific' from schedules where id = 40

Ich habe die Lösung aus diesem Artikel unten, die gerade GOLD ist !!! Es erklärt dieses nicht triviale Problem sehr deutlich. Lesen Sie es, wenn Sie die Verwaltung von pstgrsql TZ besser verstehen möchten.

Ausdrücken von PostgreSQL-Zeitstempeln ohne Zonen in Ortszeit

Hier ist was los ist. Zunächst sollten Sie wissen, dass die PST-Zeitzone 8 Stunden hinter der UTC-Zeitzone liegt. Beispiel: 1. Januar 2014, 4:30 PM= PST (Mi, 1. Januar 2014, 16:00:30 -0800) ist Entspricht dem 2. Januar 2014, 00:30 Uhr UTC (Do, 2. Januar 2014, 00:00:30 +0000). Jeder Zeitpunkt nach 16:00 Uhr in PST wird auf den nächsten Tag verschoben und als UTC interpretiert.

Wie Erwin Brandstetter bereits erwähnt hat postresql zwei Arten von Zeitstempeldatentypen, einen mit und einen ohne Zeitzone. Wenn Ihre Zeitstempel eine Zeitzone enthalten, dann eine einfache:

$ select starts_at AT TIME ZONE 'US/Pacific' from schedules where id = 40

wird funktionieren. Wenn Ihr Zeitstempel jedoch zeitlos ist, funktioniert die Ausführung des obigen Befehls nicht, und Sie müssen Ihren zeitlosen Zeitstempel ZUERST in einen Zeitstempel mit einer Zeitzone, nämlich einer UTC-Zeitzone, konvertieren und NUR DANN in die gewünschte "PST" oder "US/Pacific '(die bis auf einige Probleme mit der Sommerzeit gleich sind. Ich denke, Sie sollten mit beiden in Ordnung sein).

Lassen Sie mich anhand eines Beispiels demonstrieren, wie ich einen zeitzonenlosen Zeitstempel erstelle. Nehmen wir der Einfachheit halber an, dass unsere lokale Zeitzone in der Tat "PST" ist (wenn dies nicht der Fall ist, wird es ein wenig komplizierter, was für die Zwecke dieser Erklärung nicht erforderlich ist).

Angenommen, ich habe:

$ select timestamp '2014-01-2 00:30:00' AS a, timestamp '2014-01-2 00:30:00' AT TIME ZONE 'UTC' AS b,  timestamp '2014-01-2 00:30:00' AT TIME ZONE 'UTC' AT TIME ZONE 'PST' AS c, timestamp '2014-01-2 00:30:00' AT TIME ZONE 'PST' AS d

Dies wird ergeben:

"a"=>"2014-01-02 00:30:00"   (This is the timezoneless timestamp)
"b"=>"2014-01-02 00:30:00+00" (This is the UTC TZ timestamp, note that up to a timezone, it is equivalent to the timezoneless one)
"c"=>"2014-01-01 16:30:00" (This is the correct 'PST' TZ conversion of the UTC timezone, if you read the documentation postgresql will not print the actual TZ for this conversion)
"d"=>"2014-01-02 08:30:00+00"

Der letzte Zeitstempel ist der Grund für die Verwirrung hinsichtlich der Konvertierung des zeitzonenlosen Zeitstempels von UTC nach 'PST' in postgresql. Wenn wir schreiben:

timestamp '2014-01-2 00:30:00' AT TIME ZONE 'PST' AS d

Wir nehmen einen zeitlosen Zeitstempel und versuchen, ihn in 'PST TZ umzuwandeln (wir gehen indirekt davon aus, dass postgresql versteht, dass der Zeitstempel von einer UTC TZ konvertiert werden soll, aber postresql hat eigene Pläne!). In der Praxis verwendet postgresql den zeitzonenlosen Zeitstempel ('2014-01-2 00:30:00) und behandelt ihn so, als ob er BEREITS ein' PST 'TZ-Zeitstempel wäre (dh: 2014-01-2 00:30) : 00 -0800) und konvertiert das in UTC-Zeitzone !!! Es schiebt es also 8 Stunden vor und nicht zurück! So erhalten wir (2014-01-02 08: 30: 00 + 00).

Wie auch immer, dieses letzte (nicht intuitive) Verhalten ist die Ursache aller Verwirrung. Lesen Sie den Artikel, wenn Sie eine gründlichere Erklärung wünschen, ich habe tatsächlich Ergebnisse, die ein bisschen anders sind als in diesem letzten Teil, aber die allgemeine Idee ist die gleiche.

31
AmitF

Ich weiß, dass dies eine alte ist, aber Sie können AT TIME ZONE "US/Pacific" beim Casting verwenden, um PST/PDT-Probleme zu vermeiden

SELECT starts_at :: TIMESTAMPTZ AT TIME ZONE "US/Pacific" FROM Schedules WHERE ID = '40';

7
John Rennpferd
cast(master.Stamp5DateTime as date) >= '05-05-2019' AND 

cast(master.Stamp5DateTime as date) <= '05-05-2019' 
0
Bhushan Shimpi