Mysql
 sql >> Datenbank >  >> RDS >> Mysql

MySQL-Datumszeitfelder und Sommerzeit – wie verweise ich auf die zusätzliche Stunde?

Ich habe es für meine Zwecke herausgefunden. Ich werde zusammenfassen, was ich gelernt habe (sorry, diese Notizen sind ausführlich; sie sind genauso wichtig für meine zukünftige Überweisung wie alles andere).

Im Gegensatz zu dem, was ich in einem meiner vorherigen Kommentare gesagt habe, tun die Felder DATETIME und TIMESTAMP anders verhalten. TIMESTAMP-Felder (wie in den Dokumenten angegeben) nehmen alles, was Sie ihnen im Format "JJJJ-MM-TT hh:mm:ss" senden, und konvertieren es von Ihrer aktuellen Zeitzone in UTC-Zeit. Das Gegenteil geschieht transparent, wenn Sie die Daten abrufen. DATETIME-Felder führen diese Konvertierung nicht durch. Sie nehmen alles, was Sie ihnen schicken, und speichern es einfach direkt.

Weder die DATETIME- noch die TIMESTAMP-Feldtypen können Daten in einer Zeitzone genau speichern, in der die Sommerzeit eingehalten wird . Wenn Sie "2009-11-01 01:30:00" speichern, haben die Felder keine Möglichkeit zu unterscheiden, welche Version von 1:30 Uhr Sie wollten -- die Version -04:00 oder -05:00.

Ok, also müssen wir unsere Daten in einer Nicht-DST-Zeitzone (wie UTC) speichern. TIMESTAMP-Felder können diese Daten aus Gründen, die ich erläutern werde, nicht genau verarbeiten:Wenn Ihr System auf eine DST-Zeitzone eingestellt ist, ist das, was Sie in TIMESTAMP eingeben, möglicherweise nicht das, was Sie wieder herausbekommen. Selbst wenn Sie ihm Daten senden, die Sie bereits in UTC konvertiert haben, geht es immer noch davon aus, dass die Daten in Ihrer lokalen Zeitzone liegen, und führt eine weitere Konvertierung in UTC durch. Dieser TIMESTAMP-erzwungene Local-to-UTC-back-to-local-Roundtrip ist verlustbehaftet, wenn in Ihrer lokalen Zeitzone die Sommerzeit eingehalten wird (da "2009-11-01 01:30:00" zwei verschiedenen möglichen Zeiten zugeordnet ist).

Mit DATETIME können Sie Ihre Daten in jeder gewünschten Zeitzone speichern und sicher sein, dass Sie alles zurückbekommen, was Sie senden (Sie werden nicht zu den verlustbehafteten Roundtrip-Konvertierungen gezwungen, die Ihnen TIMESTAMP-Felder aufzwingen). Die Lösung besteht also darin, ein DATETIME-Feld zu verwenden und vor dem Speichern im Feld Konvertieren Sie von Ihrer Systemzeitzone in eine beliebige Nicht-DST-Zone, in der Sie sie speichern möchten (ich denke, UTC ist wahrscheinlich die beste Option). Auf diese Weise können Sie die Konvertierungslogik in Ihre Skriptsprache einbauen, sodass Sie explizit das UTC-Äquivalent von „2009-11-01 01:30:00 -04:00“ oder „“2009-11-01 01:30“ speichern können:00 -05:00".

Eine weitere wichtige Sache, die Sie beachten sollten, ist, dass die mathematischen Funktionen von MySQL für Datum/Uhrzeit um die Sommerzeit herum nicht richtig funktionieren, wenn Sie Ihre Daten in einem DST TZ speichern. Ein Grund mehr, in UTC zu speichern.

Kurz gesagt mache ich das jetzt:

Beim Abrufen der Daten aus der Datenbank:

Interpretieren Sie die Daten aus der Datenbank explizit als UTC außerhalb von MySQL, um einen genauen Unix-Zeitstempel zu erhalten. Ich verwende dafür die strtotime()-Funktion von PHP oder die DateTime-Klasse. Es kann innerhalb von MySQL nicht zuverlässig mit den Funktionen CONVERT_TZ() oder UNIX_TIMESTAMP() von MySQL durchgeführt werden, da CONVERT_TZ nur einen 'YYYY-MM-DD hh:mm:ss'-Wert ausgibt, der unter Mehrdeutigkeitsproblemen leidet, und UNIX_TIMESTAMP() davon ausgeht Die Eingabe erfolgt in der Systemzeitzone, nicht in der Zeitzone, in der die Daten TATSÄCHLICH gespeichert wurden (UTC).

Beim Speichern der Daten in der Datenbank:

Konvertieren Sie Ihr Datum in die genaue UTC-Zeit, die Sie außerhalb von MySQL wünschen. Zum Beispiel:Mit der DateTime-Klasse von PHP können Sie "2009-11-01 1:30:00 EST" getrennt von "2009-11-01 1:30:00 EDT" angeben, dann in UTC konvertieren und die korrekte UTC-Zeit speichern in Ihr DATETIME-Feld.

Puh. Vielen Dank für jeden Beitrag und Hilfe. Hoffentlich erspart dies jemand anderem einige Kopfschmerzen auf der Straße.

Übrigens sehe ich das auf MySQL 5.0.22 und 5.0.27