Best Practices für Sommerzeit und Zeitzone [geschlossen]


2046

Ich hoffe, diese Frage und die Antworten darauf zum endgültigen Leitfaden für den Umgang mit der Sommerzeit zu machen, insbesondere für den Umgang mit den tatsächlichen Umstellungen.

Wenn Sie etwas hinzufügen möchten, tun Sie dies bitte

Viele Systeme sind darauf angewiesen, die genaue Zeit einzuhalten. Das Problem besteht darin, dass sich die Zeit aufgrund der Sommerzeit ändert und die Uhr vorwärts oder rückwärts bewegt wird.

Zum Beispiel hat man Geschäftsregeln in einem Auftragsannahmesystem, die von der Zeit der Bestellung abhängen - wenn sich die Uhr ändert, sind die Regeln möglicherweise nicht so klar. Wie soll der Zeitpunkt der Bestellung beibehalten werden? Es gibt natürlich unendlich viele Szenarien - diese ist nur eine veranschaulichende.

  • Wie sind Sie mit dem Problem der Sommerzeit umgegangen?
  • Welche Annahmen sind Teil Ihrer Lösung? (hier nach Kontext suchen)

Ebenso wichtig, wenn nicht noch wichtiger:

  • Was hast du versucht, das hat nicht funktioniert?
  • Warum hat es nicht funktioniert?

Ich würde mich für Programmierung, Betriebssystem, Datenpersistenz und andere relevante Aspekte des Problems interessieren.

Allgemeine Antworten sind großartig, aber ich würde auch gerne Details sehen, insbesondere wenn sie nur auf einer Plattform verfügbar sind.


2
@abatishchev - Dieser Weg GETDATE()unter SQL ist UTC (wie auch DateTime.Now). Und der Server wird durch keine automatischen Sommerzeitänderungen beeinflusst.
Oded

4
@Oded: Ich kann zustimmen, ob "on server" hinzugefügt wird. Dies kann sich jedoch auf andere Anwendungen auswirken, die Ortszeit benötigen. Aus diesem und anderen Gründen denke ich, dass es besser ist, die Utc-Zeit explizit anzufordern.
Abatishchev

7
UTC wird GMT vorgezogen, sowohl weil es genauer definiert ist als auch weil GMT-Definitionen auf einigen Betriebssystemen durcheinander sind. Es ist üblich, dass Menschen die Begriffe "GMT" und "UTC" als austauschbar behandeln, aber sie sind nicht vollständig. Verwenden Sie für fast alle Software- / Systemzwecke UTC. Siehe stackoverflow.com/questions/2292334/…
Chris Johnson

7
@ JoshStodola - Jon Skeets ' Antwort '.
Kenny Evitt

1
@Oded Sie können nicht davon ausgehen, dass der Server auf UTC sein wird. Ich habe Produktionsserver gesehen, bei denen die Zeitzone "UTC" war, aber die Sommerzeit angewendet wurde, also tatsächlich UTC + 1 für mehr als ein halbes Jahr. Stimmen Sie mit @abatishchev überein, explizit zu sein und zu verwenden, DateTime.UtcNowund GETUTCDATE()es zeigt auch andere Entwickler, dass Sie tatsächlich darüber nachgedacht haben
ono2012

Antworten:


940

Zusammenfassung der Antworten und anderer Daten: (bitte fügen Sie Ihre hinzu)

Tun:

  • Wenn Sie sich auf einen genauen Zeitpunkt beziehen, behalten Sie die Zeit gemäß einem einheitlichen Standard bei, der nicht von der Sommerzeit beeinflusst wird. (GMT und UTC sind in dieser Hinsicht gleichwertig, es wird jedoch bevorzugt, den Begriff UTC zu verwenden. Beachten Sie, dass UTC auch als Zulu- oder Z- Zeit bezeichnet wird.)
  • Wenn Sie stattdessen eine Zeit mit einem lokalen Zeitwert beibehalten möchten, geben Sie den lokalen Zeitversatz für diese bestimmte Zeit ab UTC an (dieser Versatz kann sich im Laufe des Jahres ändern), sodass der Zeitstempel später eindeutig interpretiert werden kann.
  • In einigen Fällen müssen Sie möglicherweise sowohl die UTC-Zeit als auch die entsprechende Ortszeit speichern . Oft wird dies mit zwei separaten Feldern durchgeführt, aber einige Plattformen unterstützen einen datetimeoffsetTyp, der beide in einem einzigen Feld speichern kann.
  • Verwenden Sie beim Speichern von Zeitstempeln als numerischen Wert die Unix-Zeit - dies ist die Anzahl der ganzen Sekunden seitdem 1970-01-01T00:00:00Z(ohne Schaltsekunden). Wenn Sie eine höhere Genauigkeit benötigen, verwenden Sie stattdessen Millisekunden. Dieser Wert sollte immer auf UTC basieren, ohne Zeitzonenanpassung.
  • Wenn Sie den Zeitstempel später möglicherweise ändern müssen, geben Sie die ursprüngliche Zeitzonen-ID an, damit Sie feststellen können, ob sich der Versatz möglicherweise gegenüber dem ursprünglich aufgezeichneten Wert geändert hat.
  • Bei der Planung zukünftiger Ereignisse wird normalerweise die Ortszeit anstelle von UTC bevorzugt, da sich der Offset häufig ändert. Siehe Antwort und Blogbeitrag .
  • Konvertieren Sie beim Speichern ganzer Daten wie Geburtstage und Jahrestage nicht in UTC oder eine andere Zeitzone.
    • Speichern Sie nach Möglichkeit in einem Datentyp, der nur ein Datum enthält und keine Tageszeit enthält.
    • Wenn ein solcher Typ nicht verfügbar ist, ignorieren Sie bei der Interpretation des Werts immer die Uhrzeit. Wenn Sie nicht sicher sein können, dass die Tageszeit ignoriert wird, wählen Sie 12:00 Uhr anstelle von 00:00 Uhr Mitternacht als sicherere repräsentative Zeit an diesem Tag.
  • Denken Sie daran, dass Zeitzonen-Offsets nicht immer eine ganzzahlige Anzahl von Stunden sind (z. B. ist die indische Standardzeit UTC + 05: 30 und Nepal verwendet UTC + 05: 45).
  • Wenn Sie Java verwenden, verwenden Sie java.time für Java 8 und höher.
  • Wenn Sie .NET verwenden , sollten Sie Noda Time verwenden .
  • Wenn Sie .NET ohne Noda Time verwenden, DateTimeOffsetist dies häufig die bessere Wahl als DateTime.
  • Wenn Sie Perl verwenden, verwenden Sie DateTime .
  • Wenn Sie Python verwenden, verwenden Sie Pytz oder Dateutil .
  • Wenn Sie JavaScript verwenden, verwenden Sie moment.js mit der Erweiterung moment- timezone .
  • Wenn Sie PHP> 5.2 verwenden, verwenden Sie die von DateTimeund DateTimeZoneKlassen bereitgestellten nativen Zeitzonenkonvertierungen . Seien Sie vorsichtig bei der Verwendung DateTimeZone::listAbbreviations()- siehe Antwort . Installieren Sie regelmäßig das PECL-Paket timezonedb, um PHP mit den aktuellen Olson-Daten auf dem neuesten Stand zu halten . siehe Antwort .
  • Wenn Sie C ++ verwenden, stellen Sie sicher, dass Sie eine Bibliothek verwenden, die die IANA-Zeitzonendatenbank ordnungsgemäß implementiert . Dazu gehören cctz , ICU und Howard Hinnants "tz" -Bibliothek .
    • Verwenden Sie Boost nicht für Zeitzonenumrechnungen. Während die API behauptet, Standard-IANA-Kennungen (auch bekannt als "zoneinfo") zu unterstützen, ordnet sie diese grob Daten im POSIX-Stil zu, ohne die umfangreiche Änderungshistorie zu berücksichtigen, die jede Zone möglicherweise hatte. (Außerdem ist die Datei nicht mehr gewartet.)
  • Wenn Sie Rust verwenden, verwenden Sie Chrono .
  • Die meisten Geschäftsregeln verwenden Zivilzeit anstelle von UTC oder GMT. Planen Sie daher, UTC-Zeitstempel in eine lokale Zeitzone zu konvertieren, bevor Sie die Anwendungslogik anwenden.
  • Denken Sie daran, dass Zeitzonen und Offsets nicht festgelegt sind und sich ändern können. In der Vergangenheit verwendeten die USA und Großbritannien beispielsweise dieselben Daten, um vorwärts zu springen und zurückzufallen. 2007 änderten die USA jedoch die Daten, an denen die Uhren geändert werden. Dies bedeutet nun, dass für 48 Wochen im Jahr der Unterschied zwischen der Londoner Zeit und der New Yorker Zeit 5 Stunden und für 4 Wochen (3 im Frühjahr, 1 im Herbst) 4 Stunden beträgt. Beachten Sie solche Elemente bei Berechnungen, die mehrere Zonen betreffen.
  • Überlegen Sie, welche Art von Zeit (tatsächliche Ereigniszeit, Sendezeit, relative Zeit, historische Zeit, wiederkehrende Zeit) welche Elemente (Zeitstempel, Zeitzonenversatz und Zeitzonenname) Sie für den korrekten Abruf speichern müssen - siehe "Zeitarten" in diese Antwort .
  • Halten Sie Ihre tzdata-Dateien für Betriebssystem, Datenbank und Anwendung untereinander und mit dem Rest der Welt synchron.
  • Stellen Sie auf Servern Hardware- und Betriebssystemuhren auf UTC anstatt auf eine lokale Zeitzone ein.
  • Unabhängig vom vorherigen Aufzählungspunkt sollte serverseitiger Code, einschließlich Websites, niemals erwarten , dass die lokale Zeitzone des Servers etwas Besonderes ist. siehe Antwort .
  • Arbeiten Sie in Ihrem Anwendungscode lieber von Fall zu Fall mit Zeitzonen als global über Einstellungen oder Standardeinstellungen für Konfigurationsdateien.
  • Verwenden Sie NTP- Dienste auf allen Servern.
  • Denken Sie bei Verwendung von FAT32 daran, dass Zeitstempel in Ortszeit und nicht in UTC gespeichert werden.
  • Denken Sie bei wiederkehrenden Ereignissen (z. B. wöchentliche TV-Sendungen) daran, dass sich die Zeit mit der Sommerzeit ändert und sich in den verschiedenen Zeitzonen unterscheidet.
  • Fragen Sie Datums- und Uhrzeitwerte immer als Untergrenze einschließlich, Obergrenze exklusiv ( >=, <) ab.

Nicht:

  • Verwechseln Sie eine "Zeitzone" nicht, z. B. America/New_Yorkmit einem "Zeitzonenversatz", z -05:00. Das sind zwei verschiedene Dinge. Siehe das Zeitzonen-Tag-Wiki .
  • Verwenden Sie das JavaScript- DateObjekt nicht, um Datums- und Zeitberechnungen in älteren Webbrowsern durchzuführen, da ECMAScript 5.1 und niedriger einen Konstruktionsfehler aufweist , bei dem die Sommerzeit möglicherweise falsch verwendet wird. (Dies wurde in ECMAScript 6/2015 behoben).
  • Vertraue niemals der Uhr des Kunden. Es kann sehr gut falsch sein.
  • Sagen Sie den Leuten nicht, dass sie "UTC immer überall verwenden sollen". Dieser weit verbreitete Ratschlag ist kurzsichtig gegenüber mehreren gültigen Szenarien, die weiter oben in diesem Dokument beschrieben wurden. Verwenden Sie stattdessen die entsprechende Zeitreferenz für die Daten, mit denen Sie arbeiten. ( Zeitstempel können UTC verwenden, zukünftige Zeitpläne und Nur-Datum-Werte sollten dies jedoch nicht.)

Testen:

  • Stellen Sie beim Testen sicher, dass Sie Länder in der westlichen, östlichen, nördlichen und südlichen Hemisphäre (tatsächlich in jedem Viertel der Welt, also 4 Regionen) testen , wobei sowohl die Sommerzeit als auch nicht (ergibt 8), und ein Land, das dies tut Verwenden Sie nicht die Sommerzeit (weitere 4, um alle Regionen abzudecken, insgesamt 12).
  • Testübergang der Sommerzeit, dh wenn Sie sich gerade im Sommer befinden, wählen Sie einen Zeitwert aus dem Winter.
  • Testen Sie Grenzfälle, z. B. eine Zeitzone mit UTC + 12, mit Sommerzeit, wobei die Ortszeit im Sommer UTC + 13 und im Winter sogar Orte mit UTC + 13 beträgt
  • Testen Sie alle Bibliotheken und Anwendungen von Drittanbietern und stellen Sie sicher, dass sie die Zeitzonendaten korrekt verarbeiten.
  • Testen Sie mindestens halbstündige Zeitzonen.

Referenz:

Andere:

  • Setzen Sie sich für Ihren Vertreter ein, um den Gräuel der Sommerzeit zu beenden. Wir können immer hoffen ...
  • Lobby für Earth Standard Time

31
Die Verwendung von GMT löst das Problem nicht wirklich. Sie müssen noch herausfinden, welches Delta das richtige ist, und hier liegt die ganze Komplexität. Das Delta kann komplex sein, um es in Systemen zu bestimmen, die von Benutzern in verschiedenen Regionen (mit unterschiedlichen Zeitplänen für die Sommerzeitumschaltung) verwendet werden, oder in Systemen, die historische / zukünftige Daten anzeigen.
Ckarras

10
Dies ist der Fall, wenn die Anwendung lediglich die aktuelle Ortszeit anzeigen muss. Wenn wir jedoch beispielsweise einen Server in Australien haben, auf dem Datum und Uhrzeit für eine Transaktion in Kanada am 2. April 2006 angezeigt werden müssen (dies war das letzte Jahr, bevor die Sommerzeit-Umschaltregeln in Kanada geändert wurden), haben Sie einen Betriebssystemaufruf das kann DateTime ("2006/04/02 14: 35Z"). ToLocalTime (). WithDaylightSavingRules ("Canada", 2006)?
ckarras

22
Ja, es gibt einen solchen Betriebssystemaufruf in Windows - SystemTimeToTzSpecificLocation. msdn.microsoft.com/en-us/library/ms724949(VS.85).aspx
Michael Madsen

7
@tchrist Vielleicht können Sie, wenn Sie hartnäckig sind.
Peter Ajtai

16
Denken Sie daran, zukünftige Daten (auch nur morgen) in UTC umzuwandeln. Sie verlieren immer etwas. Sie haben beispielsweise einen bekannten Versatz verwendet, um diese Konvertierung durchzuführen. Da das Datum jedoch in der Zukunft liegt, besteht immer die Möglichkeit, dass die Gruppe, die diese Regeln festlegt, diese Regeln ändert. Außerdem ist es praktisch unmöglich, einige zukünftige Daten in UTC umzuwandeln, da die Sommerzeit erst in diesem Jahr bekannt ist (einige Länder legen die Daten jedes Jahr fest, nicht mehr als 10 Jahre im Voraus oder basierend auf festgelegten Regeln).
Eselk

319

Ich bin nicht sicher, was ich zu den obigen Antworten hinzufügen kann, aber hier sind einige Punkte von mir:

Arten von Zeiten

Es gibt vier verschiedene Zeiten, die Sie berücksichtigen sollten:

  1. Ereigniszeit: z. B. die Zeit, zu der ein internationales Sportereignis stattfindet, oder eine Krönung / Tod / etc. Dies hängt von der Zeitzone des Ereignisses und nicht vom Betrachter ab.
  2. Fernsehzeit: ZB wird eine bestimmte Fernsehsendung weltweit um 21 Uhr Ortszeit ausgestrahlt. Wichtig, wenn Sie darüber nachdenken, die Ergebnisse (z. B. American Idol) auf Ihrer Website zu veröffentlichen
  3. Relative Zeit: zB: Diese Frage hat ein offenes Kopfgeld, das in 21 Stunden geschlossen wird. Dies ist einfach anzuzeigen
  4. Wiederkehrende Zeit: zB: Eine TV-Show läuft jeden Montag um 21 Uhr, auch wenn sich die Sommerzeit ändert.

Es gibt auch historische / alternative Zeit. Diese sind ärgerlich, da sie möglicherweise nicht auf die Standardzeit zurückgeführt werden. ZB: Julianische Daten, Daten nach einem Mondkalender auf Saturn, dem klingonischen Kalender.

Das Speichern von Start- / Endzeitstempeln in UTC funktioniert gut. Für 1 benötigen Sie einen Ereigniszeitzonennamen + Offset, der zusammen mit dem Ereignis gespeichert wird. Für 2 benötigen Sie eine lokale Zeitkennung, die in jeder Region gespeichert ist, und einen lokalen Zeitzonennamen + Offset, der für jeden Betrachter gespeichert ist (dies kann aus der IP abgeleitet werden, wenn Sie sich in einer Krise befinden). Für 3 in UTC Sekunden speichern und keine Zeitzonen erforderlich. 4 ist ein Sonderfall von 1 oder 2, je nachdem, ob es sich um ein globales oder ein lokales Ereignis handelt. Sie müssen jedoch auch ein zum Zeitstempel erstelltes Ereignis speichern, damit Sie feststellen können, ob sich eine Zeitzonendefinition vor oder nach dem Erstellen dieses Ereignisses geändert hat. Dies ist erforderlich, wenn Sie historische Daten anzeigen müssen.

Speicherzeiten

  • Speichern Sie die Zeit immer in UTC
  • In angezeigte Ortszeit konvertieren (lokal wird vom Benutzer definiert, der die Daten betrachtet)
  • Beim Speichern einer Zeitzone benötigen Sie den Namen, den Zeitstempel und den Versatz. Dies ist erforderlich, weil Regierungen manchmal die Bedeutung ihrer Zeitzonen ändern (z. B. die US-Regierung hat die Sommerzeitdaten geändert) und Ihre Anwendung die Dinge ordnungsgemäß handhaben muss ... z. B.: Der genaue Zeitstempel, in dem Episoden von LOST sowohl vor als auch nach den Sommerzeitregeln angezeigt wurden geändert.

Offsets und Namen

Ein Beispiel für das Obige wäre:

Das Fußball-WM-Endspiel fand am 11. Juli 2010 um 19:00 UTC in Südafrika (UTC + 2 - SAST) statt.

Mit diesen Informationen können wir historisch den genauen Zeitpunkt bestimmen, zu dem das WCS-Finale 2010 stattfand, selbst wenn sich die Definition der südafrikanischen Zeitzone ändert, und dies den Zuschauern in ihrer lokalen Zeitzone zum Zeitpunkt der Abfrage der Datenbank anzeigen.

Systemzeit

Sie müssen auch Ihre Betriebssystem-, Datenbank- und Anwendungs-tzdata-Dateien sowohl untereinander als auch mit dem Rest der Welt synchron halten und beim Upgrade ausgiebig testen. Es ist nicht ungewöhnlich, dass eine Drittanbieter-App, auf die Sie angewiesen sind, eine TZ-Änderung nicht korrekt verarbeitet hat.

Stellen Sie sicher, dass die Hardware-Uhren auf UTC eingestellt sind. Wenn Sie Server auf der ganzen Welt ausführen, stellen Sie sicher, dass deren Betriebssysteme auch für die Verwendung von UTC konfiguriert sind. Dies wird deutlich, wenn Sie stündlich gedrehte Apache-Protokolldateien von Servern in mehreren Zeitzonen kopieren müssen. Das Sortieren nach Dateinamen funktioniert nur, wenn alle Dateien mit derselben Zeitzone benannt sind. Es bedeutet auch, dass Sie keine Datumsberechnung in Ihrem Kopf durchführen müssen, wenn Sie von einer Box zur nächsten wechseln und Zeitstempel vergleichen müssen.

Führen Sie außerdem ntpd für alle Boxen aus.

Kunden

Vertrauen Sie niemals dem Zeitstempel, den Sie von einem Client-Computer erhalten, als gültig. Zum Beispiel die Date: HTTP-Header oder ein Javascript- Date.getTime()Aufruf. Diese sind in Ordnung, wenn sie als undurchsichtige Bezeichner verwendet werden oder wenn während einer einzelnen Sitzung auf demselben Client Datumsberechnungen durchgeführt werden. Versuchen Sie jedoch nicht, diese Werte mit etwas auf dem Server zu vergleichen. Ihre Clients führen kein NTP aus und verfügen möglicherweise nicht unbedingt über einen funktionierenden Akku für ihre BIOS-Uhr.

Wissenswertes

Schließlich werden Regierungen manchmal sehr seltsame Dinge tun:

Die Standardzeit in den Niederlanden betrug vom 1909-05-01 bis zum 1937-06-30 laut Gesetz genau 19 Minuten und 32,13 Sekunden vor UTC. Diese Zeitzone kann im HH: MM-Format nicht genau dargestellt werden.

Ok, ich denke ich bin fertig.


6
Diese Antwort hat einige großartige Punkte. Ich wollte besonders auf diesen Teil hinweisen: "Wiederkehrende Zeit: zB: Eine TV-Show läuft jeden Montag um 21 Uhr, auch wenn sich die Sommerzeit ändert." Das Speichern von Zeiten in UTC in der DB und das anschließende Konvertieren für die Anzeige helfen dabei viele der kniffligen Aspekte des Umgangs mit Zeitzonen. Die Behandlung von "wiederkehrenden Ereignissen", die DST-Barrieren überschreiten, wird jedoch viel schwieriger.
Jared Hales

45
+1 für die Trivia. Wenn Sie den Inhalt interessant halten, macht diese Aufgabe mehr Spaß, was zu einer höheren Produktivität führen kann :)
Chris

4
Viele gute Sachen in dieser Antwort, aber ein paar Probleme. 1) Viele Zeitzonenabkürzungen sind nicht eindeutig. siehe hier 2) Sie möchten nicht immer in UTC speichern. Meistens - ja, aber der Kontext ist wichtig. In Ihren Begriffen würde die Fernsehzeit nicht in UTC gespeichert. Manchmal ist es auch rechtswidrig oder gegen die Richtlinien, die Ortszeit nicht zu speichern - hier sind Dinge wie DateTimeOffset(oder gleichwertig) nützlich. Ansonsten gut aufschreiben.
Matt Johnson-Pint

1
Alle sind sich also einig, dass die Joda-Bibliothek bei weitem das beste Werkzeug für diesen Job ist. Wir müssen jedoch die JODA-JAR-Datei gemäß diesem Artikel ( joda.org/joda-time/tz_update.html ) ständig aktualisieren (neu erstellen ), um auf dem neuesten Stand der Zeitzoneninformationen zu bleiben. Gibt es eine Standardmethode zum Herunterladen der neuesten Zeitzonendaten von der IANA-Website ( iana.org/time-zones ) und zum Neuerstellen der Joda-Bibliothek? Mit anderen Worten, ist es möglich, diesen Prozess zu automatisieren, anstatt ihn manuell durchzuführen?
Saravana_pc

2
Die niederländischen Trivia sehen echt aus. ietf.org/rfc/rfc3339.txt Abschnitt 5.8. Auf halbem Weg dachte ich, jemand würde an unserem Bein ziehen.
Ruffin

89

Dies ist ein wichtiges und überraschend schwieriges Thema. Die Wahrheit ist, dass es keinen völlig zufriedenstellenden Standard für die Dauer der Zeit gibt. Zum Beispiel reichen der SQL-Standard und das ISO-Format (ISO 8601) eindeutig nicht aus.

Aus konzeptioneller Sicht werden normalerweise zwei Arten von Zeit-Datum-Daten behandelt, und es ist zweckmäßig, sie zu unterscheiden (die oben genannten Standards nicht): " physische Zeit " und " bürgerliche Zeit ".

Ein "physischer" Zeitpunkt ist ein Punkt in der kontinuierlichen universellen Zeitachse, mit dem sich die Physik befasst (natürlich ohne Berücksichtigung der Relativitätstheorie). Dieses Konzept kann beispielsweise in UTC ausreichend codiert und beibehalten werden (wenn Sie Schaltsekunden ignorieren können).

Eine "zivile" Zeit ist eine Datums- / Uhrzeitspezifikation, die zivilen Normen folgt: Ein Zeitpunkt wird hier vollständig durch eine Reihe von Datums- / Uhrzeitfeldern (Y, M, D, H, MM, S, FS) plus eine TZ (Zeitzonenspezifikation) spezifiziert. (eigentlich auch ein "Kalender"; aber nehmen wir an, wir beschränken die Diskussion auf den Gregorianischen Kalender). Eine Zeitzone und ein Kalender ermöglichen (im Prinzip) die Zuordnung von einer Darstellung zur anderen. Aber zivile und physische Zeitpunkte sind grundsätzlich unterschiedliche Arten von Größen, und sie sollten konzeptionell getrennt gehalten und unterschiedlich behandelt werden (eine Analogie: Arrays von Bytes und Zeichenketten).

Das Problem ist verwirrend, weil wir austauschbar von solchen Ereignissen sprechen und weil die bürgerlichen Zeiten politischen Veränderungen unterliegen. Das Problem (und die Notwendigkeit, diese Konzepte zu unterscheiden) wird für zukünftige Ereignisse offensichtlicher. Beispiel (aus meiner Diskussion hier entnommen .

John zeichnet in seinem Kalender eine Erinnerung für ein Ereignis zur Datumszeit auf 2019-Jul-27, 10:30:00, TZ = Chile/Santiago(das GMT-4 versetzt hat, daher entspricht es UTC 2019-Jul-27 14:30:00). Aber eines Tages in der Zukunft beschließt das Land, den TZ-Offset auf GMT-5 zu ändern.

Nun, wenn der Tag kommt ... sollte diese Erinnerung bei auslösen

A) 2019-Jul-27 10:30:00 Chile/Santiago = UTC time 2019-Jul-27 15:30:00?

oder

B) 2019-Jul-27 9:30:00 Chile/Santiago = UTC time 2019-Jul-27 14:30:00?

Es gibt keine richtige Antwort, es sei denn, man weiß, was John konzeptionell meinte, als er dem Kalender sagte "Bitte ruf mich an 2019-Jul-27, 10:30:00 TZ=Chile/Santiago".

Meinte er eine "bürgerliche Datumszeit" ("wenn die Uhren in meiner Stadt 10:30 anzeigen")? In diesem Fall ist A) die richtige Antwort.

Oder meinte er einen "physischen Moment der Zeit", einen Punkt in der Kontinuumslinie unseres Universums, sagen wir "wenn die nächste Sonnenfinsternis passiert". In diesem Fall ist Antwort B) die richtige.

Einige Datums- / Zeit-APIs machen diese Unterscheidung richtig: Unter ihnen Jodatime , die die Grundlage für die nächste (dritte!) Java DateTime-API (JSR 310) bildet.


1
Ein weiterer zu berücksichtigender Punkt, den ich in APIs nicht angesprochen habe, ist, dass es selbst bei Angabe von Zeit und Zeitzone mindestens zwei plausible Bedeutungen für z. B. "13: 00: 00EDT" gibt. Es könnte sich um etwas handeln, von dem bekannt ist, dass es um 13 Uhr Ortszeit aufgetreten ist, von dem angenommen wurde, dass es die östliche Sommerzeit war, oder auf etwas, von dem bekannt ist, dass es zu dem Zeitpunkt aufgetreten ist, als die östliche Zeit 13:00 Uhr erreichte, was vermutlich der Fall ist sind an einem Ort aufgetreten, an dem die östliche Sommerzeit beobachtet wurde. Wenn man viele Zeitstempel hat, bei denen die Zeitzoneninformationen möglicherweise falsch sind (z. B. Digitalkameradateien) ...
Supercat

1
... zu wissen, ob sie eine genaue lokale oder globale Zeit widerspiegeln, kann wichtig sein, um zu bestimmen, wie sie korrigiert werden sollen.
Supercat

3
Offensichtlich will John A), weil die Leute um 8:30 Uhr zur Arbeit gehen, unabhängig von der Sommerzeit oder der Zeitzone. Wenn sie in die Sommerzeit gehen, gehen sie um 8:30 Uhr zur Arbeit, wenn sie die Sommerzeit verlassen, gehen sie um 8:30 Uhr zur Arbeit. Wenn das Land beschließt, in eine andere Zeitzone zu ziehen, werden sie jeden
Tag

59

Machen Sie eine klare architektonische Trennung von Bedenken - um genau zu wissen, welche Ebene mit Benutzern interagiert und Datum und Uhrzeit für / von der kanonischen Darstellung (UTC) ändern muss. Nicht-UTC-Datum-Uhrzeit ist eine Darstellung (folgt der lokalen Zeitzone des Benutzers), UTC-Zeit ist ein Modell (bleibt für Back-End- und Mid-Tiers eindeutig).

Entscheiden Sie auch, was Ihr tatsächliches Publikum ist, was Sie nicht bedienen müssen und wo Sie die Grenze ziehen . Berühren Sie keine exotischen Kalender, es sei denn, Sie haben tatsächlich wichtige Kunden dort und ziehen Sie dann separate benutzerbezogene Server nur für diese Region in Betracht.

Wenn Sie den Standort des Benutzers erfassen und verwalten können, verwenden Sie den Standort für die systematische Konvertierung von Datum und Uhrzeit (z. B. .NET-Kultur oder eine SQL-Tabelle), bieten Sie dem Endbenutzer jedoch die Möglichkeit, Überschreibungen auszuwählen, wenn die Datums- und Uhrzeit für Ihre Benutzer kritisch ist.

Wenn es sich um historische Prüfungsverpflichtungen handelt (z. B. um genau zu sagen, wann Jo in AZ vor 2 Jahren im September eine Rechnung bezahlt hat), behalten Sie sowohl die UTC- als auch die Ortszeit für die Aufzeichnung bei (Ihre Umrechnungstabellen ändern sich im Laufe der Zeit).

Definieren Sie die zeitreferenzielle Zeitzone für Daten, die in großen Mengen vorliegen - wie Dateien, Webdienste usw. Angenommen, das Unternehmen an der Ostküste verfügt über ein Rechenzentrum in CA - Sie müssen fragen und wissen, was sie als Standard verwenden, anstatt das eine oder andere anzunehmen.

Vertrauen Sie keinen Zeitzonen-Offsets, die in die Textdarstellung der Datums- und Uhrzeitangabe eingebettet sind, und akzeptieren Sie nicht, diese zu analysieren und zu befolgen. Fordern Sie stattdessen immer an, dass Zeitzone und / oder Referenzzone explizit definiert werden müssen . Sie können problemlos Zeit mit PST-Offset empfangen, aber die Zeit ist tatsächlich EST, da dies die Referenzzeit des Clients ist und die Datensätze gerade auf einem Server exportiert wurden, der sich in PST befindet.


40

Sie müssen über die Olson tz-Datenbank Bescheid wissen , die unter ftp://elsie.nci.nih.gov/pub http://iana.org/time-zones/ verfügbar ist . Es wird mehrmals pro Jahr aktualisiert, um die häufig in letzter Minute vorgenommenen Änderungen zu berücksichtigen, wann (und ob) in verschiedenen Ländern der Welt zwischen Winter- und Sommerzeit (Standard- und Sommerzeit) umgeschaltet werden soll. Im Jahr 2009 war die letzte Veröffentlichung 2009; im Jahr 2010 war es 2010n; im Jahr 2011 war es 2011n; Ende Mai 2012 war die Veröffentlichung 2012c. Beachten Sie, dass in zwei separaten Archiven (tzcode20xxy.tar.gz und tzdata20xxy.tar.gz) eine Reihe von Codes zum Verwalten der Daten und der tatsächlichen Zeitzonendaten selbst vorhanden sind. Sowohl Code als auch Daten sind gemeinfrei.

Dies ist die Quelle für Zeitzonennamen wie America / Los_Angeles (und Synonyme wie US / Pacific).

Wenn Sie verschiedene Zonen im Auge behalten müssen, benötigen Sie die Olson-Datenbank. Wie andere empfohlen haben, möchten Sie die Daten auch in einem festen Format speichern - normalerweise wird UTC ausgewählt -, zusammen mit einer Aufzeichnung der Zeitzone, in der die Daten generiert wurden. Möglicherweise möchten Sie zwischen dem Versatz von UTC zum Zeitpunkt und dem Namen der Zeitzone unterscheiden. das kann später einen Unterschied machen. Wenn Sie wissen, dass es sich derzeit um 2010-03-28T23: 47: 00-07: 00 (US / Pazifik) handelt, können Sie möglicherweise auch den Wert 2010-11-15T12: 30 interpretieren, der vermutlich in PST angegeben ist ( Pacific Standard Time) anstelle von PDT (Pacific Daylight Saving Time).

Die Standardschnittstellen der C-Bibliothek sind bei solchen Dingen nicht besonders hilfreich.


Die Olson-Daten wurden verschoben, zum Teil, weil AD Olson bald in den Ruhestand geht, und zum Teil, weil gegen die Betreuer eine (inzwischen abgewiesene) Klage wegen Urheberrechtsverletzung erhoben wurde. Die Zeitzonendatenbank wird jetzt unter der Schirmherrschaft von IANA , der Internet Assigned Numbers Authority, verwaltet. Auf der Startseite befindet sich ein Link zu "Zeitzonendatenbank" . Die Diskussions-Mailingliste ist jetzt tz@iana.org; Die Ankündigungsliste ist tz-announce@iana.org.


12
Die Olson-Datenbank enthält auch historische Daten, was sie besonders nützlich für die Behandlung der Sommerzeit macht. Es ist beispielsweise bekannt, dass ein UTC-Wert, der dem 31. März 2000 in den USA entspricht, nicht in der Sommerzeit ist, sondern ein UTC-Wert, der dem 31. März 2008 in den USA entspricht.
Josh Kelley

3
Das Unicode-Konsortium verwaltet eine Zuordnung zwischen Olson-Bandzonen-IDs und Windows-Zeitzonen-IDs: unicode.org/repos/cldr-tmp/trunk/diff/supplemental/…
Josh Kelley

Aktualisierter Link für die Seite des Unicode-Konsortiums: unicode.org/repos/cldr-tmp/trunk/diff/supplemental/…
Span

Wo kann man Informationen zum Parsen der Olson-Dateien finden? Ich möchte es in eine DB-Tabelle kompilieren, kann aber nicht herausfinden, wie ich die Dateien lesen soll
Shealtiel

@gidireich: Die Hauptinformationen werden mit den Daten gefunden und sind nicht leicht zu verstehen. Die Hauptdokumentation dazu befindet sich in der zic.8Manpage (oder zic.8.txt). Sie benötigen die tzcode2011i.tar.gzDatei anstelle oder ebenso wie die tzdata2011i.tar.gzDatei, um diese Informationen zu erhalten.
Jonathan Leffler

26

Nehmen Sie im Allgemeinen den lokalen Zeitversatz (einschließlich des DST-Versatzes) in gespeicherte Zeitstempel auf: UTC allein reicht nicht aus, wenn Sie den Zeitstempel später in seiner ursprünglichen Zeitzone (und DST-Einstellung) anzeigen möchten.

Beachten Sie, dass der Offset nicht immer eine ganzzahlige Anzahl von Stunden ist (z. B. ist die indische Standardzeit UTC + 05: 30).

Geeignete Formate sind beispielsweise ein Tupel (Unix-Zeit, Offset in Minuten) oder ISO 8601 .


5
Für die Anzeige ist der Versatz perfekt. Wenn Sie Änderungen vornehmen möchten, reicht der Offset immer noch nicht aus. Sie müssen auch die Zeitzone kennen, da für den neuen Wert möglicherweise ein anderer Versatz erforderlich ist.
Matt Johnson-Pint

23

Das Überschreiten der Grenze zwischen "Computerzeit" und "Menschenzeit" ist ein Albtraum. Das wichtigste ist, dass es keinen Standard für die Regeln für Zeitzonen und Sommerzeit gibt. Den Ländern steht es jederzeit frei, ihre Zeitzonen- und Sommerzeitregeln zu ändern.

Einige Länder, z. B. Israel, Brasilien, entscheiden jedes Jahr, wann die Sommerzeit sein soll. Daher ist es unmöglich, im Voraus zu wissen, wann (wenn) die Sommerzeit in Kraft tritt. Andere haben feste (ish) Regeln, wann die Sommerzeit in Kraft ist. Andere Länder verwenden die Sommerzeit nicht wie alle.

Zeitzonen müssen keine vollen Stundenunterschiede zu GMT sein. Nepal ist +5,45. Es gibt sogar Zeitzonen mit +13. Das bedeutet, dass:

SUN 23:00 in Howland Island (-12)
MON 11:00 GMT 
TUE 00:00 in Tonga (+13)

sind alle zur gleichen Zeit, aber 3 verschiedene Tage!

Es gibt auch keinen klaren Standard für die Abkürzungen für Zeitzonen und wie sie sich in der Sommerzeit ändern, sodass Sie am Ende folgende Dinge erhalten:

AST Arab Standard Time     UTC+03
AST Arabian Standard Time  UTC+04
AST Arabic Standard Time   UTC+03

Der beste Rat ist, sich so weit wie möglich von der Ortszeit fernzuhalten und sich an UTC zu halten, wo Sie können. Konvertieren Sie nur zum letztmöglichen Zeitpunkt in Ortszeiten.

Stellen Sie beim Testen sicher, dass Sie Länder in der westlichen und östlichen Hemisphäre testen, wobei sowohl die Sommerzeit läuft als auch nicht und ein Land, in dem die Sommerzeit nicht verwendet wird (insgesamt 6).


In Bezug auf Israel - das ist halb wahr. Obwohl die Zeit für die Sommerzeitänderung kein bestimmtes Datum im julianischen Kalender ist, gibt es eine Regel, die auf dem hebräischen Kalender basiert (es gab eine Änderung im Jahr 2014). Wie auch immer, die allgemeine Idee ist richtig - diese Dinge könnten und werden sich von Zeit zu Zeit ändern
Yaron U.

1
Auch AST = Atlantic Standard Time. Der beste Rat ist als Ausgangspunkt in Ordnung, aber Sie müssen den Rest dieser Seite lesen und ein kleines Gebet sprechen, damit Sie ihn für eine Weile richtig verstehen.
DavidWalley

20

Für PHP:

Die DateTimeZone-Klasse in PHP> 5.2 basiert bereits auf der Olson-Datenbank, die von anderen erwähnt wird. Wenn Sie also Zeitzonenkonvertierungen in PHP und nicht in der Datenbank durchführen, können Sie nicht mit (schwer verständlichen) Olson-Dateien arbeiten.

PHP wird jedoch nicht so häufig aktualisiert wie die Olson-Datenbank. Wenn Sie also nur die Zeitzonen-Konvertierungen von PHP verwenden, erhalten Sie möglicherweise veraltete Sommerzeitinformationen und können die Richtigkeit Ihrer Daten beeinflussen. Es wird zwar nicht häufig erwartet, dass dies häufig vorkommt, dies kann jedoch vorkommen , wenn Sie eine große Anzahl von Benutzern weltweit haben.

Verwenden Sie das timezonedb pecl-Paket, um das oben genannte Problem zu beheben . Seine Funktion besteht darin, die Zeitzonendaten von PHP zu aktualisieren. Installieren Sie dieses Paket so oft, wie es aktualisiert wird. (Ich bin nicht sicher, ob die Updates für dieses Paket genau den Olson-Updates folgen, aber es scheint mit einer Häufigkeit aktualisiert zu werden, die zumindest sehr nahe an der Häufigkeit der Olson-Updates liegt.)


18

Wenn Ihr Design dies zulässt, vermeiden Sie die lokale Zeitumrechnung insgesamt!

Ich weiß, dass dies für manche vielleicht verrückt klingt, aber denken Sie an UX: Benutzer verarbeiten nahe relative Daten (heute, gestern, nächsten Montag) schneller als absolute Daten (2010.09.17, Freitag, 17. September) auf einen Blick. Und wenn Sie mehr darüber nachdenken, ist die Genauigkeit der Zeitzonen (und der Sommerzeit) umso wichtiger, je näher das Datum liegt. now()Wenn Sie also Datums- / Datumsangaben in einem relativen Format für +/- 1 oder 2 Wochen ausdrücken können, ist der Rest von Die Daten können UTC sein und es wird 95% der Benutzer nicht allzu wichtig sein.

Auf diese Weise können Sie alle Daten in UTC speichern und die relativen Vergleiche in UTC durchführen und dem Benutzer einfach UTC-Daten außerhalb Ihres relativen Datumsschwellenwerts anzeigen.

Dies kann auch für Benutzereingaben gelten (im Allgemeinen jedoch eingeschränkter). Die Auswahl aus einer Dropdown-Liste mit nur {Gestern, Heute, Morgen, Nächsten Montag, Nächsten Donnerstag} ist für den Benutzer so viel einfacher und einfacher als eine Datumsauswahl. Dattelpflücker sind einige der schmerzauslösendsten Bestandteile des Formularfüllens. Natürlich funktioniert dies nicht in allen Fällen, aber Sie können sehen, dass nur ein wenig cleveres Design erforderlich ist, um es sehr leistungsfähig zu machen.


16

Obwohl ich es noch nicht ausprobiert habe, wäre ein Ansatz für Zeitzonenanpassungen, den ich als überzeugend empfinden würde, wie folgt:

  1. Speichern Sie alles in UTC.

  2. Erstellen Sie eine Tabelle TZOffsetsmit drei Spalten: RegionClassId, StartDateTime und OffsetMinutes (int, in Minuten).

In der Tabelle speichert eine Liste von Daten und Zeiten , wenn die lokale Zeit verändert, und um wie viel. Die Anzahl der Regionen in der Tabelle und die Anzahl der Daten hängen davon ab, welche Datumsbereiche und Regionen der Welt Sie unterstützen müssen. Stellen Sie sich das so vor, als wäre es ein "historisches" Datum, obwohl die Daten die Zukunft bis zu einer praktischen Grenze einschließen sollten.

Wenn Sie die Ortszeit einer UTC-Zeit berechnen müssen, gehen Sie wie folgt vor:

SELECT DATEADD('m', SUM(OffsetMinutes), @inputdatetime) AS LocalDateTime
FROM   TZOffsets
WHERE  StartDateTime <= @inputdatetime
       AND RegionClassId = @RegionClassId;

Möglicherweise möchten Sie diese Tabelle in Ihrer App zwischenspeichern und LINQ oder ein ähnliches Mittel verwenden, um die Abfragen auszuführen, anstatt auf die Datenbank zuzugreifen.

Diese Daten können aus der gemeinfreien tz-Datenbank destilliert werden .

Vorteile und Fußnoten dieses Ansatzes:

  1. Es werden keine Regeln in den Code eingebrannt. Sie können die Offsets für neue Regionen oder Datumsbereiche problemlos anpassen.
  2. Sie müssen nicht alle Datums- oder Regionsbereiche unterstützen, sondern können sie nach Bedarf hinzufügen.
  3. Regionen müssen nicht direkt geopolitischen Grenzen entsprechen. Um Doppelzeilen zu vermeiden (z. B. behandeln die meisten Staaten in den USA die Sommerzeit auf dieselbe Weise), können Sie breite RegionClass-Einträge verwenden, die in einer anderen Tabelle mit traditionelleren Listen von verknüpft sind Staaten, Länder usw.
  4. In Situationen wie den USA, in denen sich das Start- und Enddatum der Sommerzeit in den letzten Jahren geändert hat, ist dies recht einfach zu handhaben.
  5. Da im Feld StartDateTime auch eine Uhrzeit gespeichert werden kann, ist die Standardumschaltzeit um 2:00 Uhr problemlos zu handhaben.
  6. Nicht überall auf der Welt wird eine 1-stündige Sommerzeit verwendet. Dies behandelt diese Fälle leicht.
  7. Die Datentabelle ist plattformübergreifend und kann ein separates Open-Source-Projekt sein, das von Entwicklern verwendet werden kann, die nahezu jede Datenbankplattform oder Programmiersprache verwenden.
  8. Dies kann für Offsets verwendet werden, die nichts mit Zeitzonen zu tun haben. Zum Beispiel die 1-Sekunden-Anpassungen, die von Zeit zu Zeit vorgenommen werden, um die Erdrotation anzupassen, historische Anpassungen an und innerhalb des Gregorianischen Kalenders usw.
  9. Da dies in einer Datenbanktabelle enthalten ist, können Standardberichtsabfragen usw. die Daten nutzen, ohne den Geschäftslogikcode zu durchlaufen.
  10. Dies behandelt auch Zeitzonen-Offsets, wenn Sie dies möchten, und kann sogar spezielle historische Fälle berücksichtigen, in denen eine Region einer anderen Zeitzone zugewiesen ist. Sie benötigen lediglich ein Anfangsdatum, das jeder Region einen Zeitzonenversatz mit einem minimalen Startdatum zuweist. Dies würde die Erstellung mindestens einer Region für jede Zeitzone erfordern, aber Sie könnten interessante Fragen stellen wie: "Was ist der Unterschied in der Ortszeit zwischen Yuma, Arizona und Seattle, Washington am 2. Februar 1989 um 5:00 Uhr?" (Subtrahieren Sie einfach eine SUMME () von der anderen).

Der einzige Nachteil dieses oder eines anderen Ansatzes besteht darin, dass die Umrechnungen von der Ortszeit zu GMT nicht perfekt sind, da jede DST-Änderung, die einen negativen Versatz zur Uhr aufweist, eine bestimmte Ortszeit wiederholt . Ich fürchte, es gibt keine einfache Möglichkeit, damit umzugehen. Dies ist einer der Gründe, warum das Speichern von Ortszeiten in erster Linie eine schlechte Nachricht ist.


8
Ihre Datenbankidee wurde bereits als Olson-Datenbank implementiert. Während die Sommerzeit eine Überlappung erzeugt, kann die Angabe der sommerzeitspezifischen Zeitzone zur Behebung des Problems beitragen. 2:15 EST und 2:15 EDT sind unterschiedliche Zeiten. Wie in anderen Beiträgen erwähnt, wird durch die Angabe des Versatzes auch die Mehrdeutigkeit behoben.
BillThor

5
Das große Problem bei der Pflege Ihrer eigenen Datenbank besteht darin, sie auf dem neuesten Stand zu halten. Olson und Windows werden für Sie gepflegt. Ich hatte mehr als einen Fall von schlechten Sommerzeitübergängen, weil Tabellen veraltet waren. Das vollständige Herausreißen und Verlassen auf ein Framework oder eine Datenbank auf Betriebssystemebene ist viel zuverlässiger.
Matt Johnson-Pint

4
Erstellen Sie keine eigene Datenbank : Verlassen Sie sich immer auf die API des Systems!
Alex

15

Ich hatte kürzlich ein Problem in einer Webanwendung, bei der bei einem Ajax-Post-Back die Datums- / Uhrzeitangabe, die zu meinem serverseitigen Code zurückkehrte, sich von der Datums- / Uhrzeitangabe unterschied.

Dies hatte höchstwahrscheinlich mit meinem JavaScript-Code auf dem Client zu tun, der das Datum für die Rücksendung als Zeichenfolge an den Client festlegte, da JavaScript die Zeitzone und die Sommerzeit anpasste und in einigen Browsern berechnet wurde, wann die Sommerzeit angewendet werden soll schien anders zu sein als bei anderen.

Am Ende habe ich mich dafür entschieden, Datums- und Zeitberechnungen auf dem Client vollständig zu entfernen und sie mit einem Ganzzahlschlüssel auf meinen Server zurückzusenden, der dann auf dem Server in Datum und Uhrzeit übersetzt wurde, um konsistente Transformationen zu ermöglichen.

Ich lerne daraus: Verwenden Sie in Webanwendungen keine JavaScript-Datums- und Zeitberechnungen, es sei denn, Sie müssen dies ABSOLUT tun.


Javascript wird auf dem Client-Computer ausgeführt, nicht auf dem Server-Computer. Die Basis-Datumszeit von Javascript ist die Datums- / Uhrzeit des Clients, nicht die Datums- / Uhrzeit des Servers.
BalusC

Hallo BalusC. Ich verstehe das (aus meinem ursprünglichen Beitrag: "Javacode-Skript auf dem Client, der das Datum erstellt hat ..."). Mein Problem war, dass bestimmte Client-Computer die Sommerzeit auf eine Weise und einige andere auf eine andere Weise verarbeiteten. Deshalb habe ich die gesamte Verarbeitung serverseitig verschoben, um die Verrücktheit des Browsers zu verhindern
Joon

@ Joon - und es gibt Fehler in Javascript-Implementierungen, die Sie nicht erkennen oder zulassen können. Verwenden Sie also niemals clientseitige ECMAScript-Datumsberechnungen für wichtige Dinge (obwohl Sie sonst einen ziemlich guten Job machen können).
RobG

14

Ich habe dies bei zwei Arten von Systemen festgestellt: „Schichtplanungssysteme (z. B. Fabrikarbeiter)“ und „gasabhängige Managementsysteme)…

23 und 25 Stunden lange Tage sind ein Schmerz, mit dem man fertig werden muss, ebenso wie 8-Stunden-Schichten, die 7 Stunden oder 9 Stunden dauern. Das Problem ist, dass Sie feststellen werden, dass jeder Kunde oder sogar jede Abteilung des Kunden unterschiedliche Regeln hat (oft ohne zu dokumentieren), was sie in diesen speziellen Fällen tun.

Einige Fragen werden dem Kunden am besten erst gestellt, nachdem er für Ihre Standard-Software bezahlt hat. Es ist sehr selten, dass ein Kunde beim Kauf von Software im Voraus über diese Art von Problem nachdenkt.

Ich denke in jedem Fall sollten Sie die Zeit in UTC aufzeichnen und in / von der Ortszeit konvertieren, bevor Sie das Datum / die Uhrzeit speichern. Selbst wenn Sie wissen, in welcher Zeit sich eine bestimmte Zeit befindet, kann dies mit Sommerzeit und Zeitzonen schwierig sein.


6
Meine Freundin, eine Krankenschwester, arbeitet nachts und muss während der Sommerzeitumschaltung die Zeitzone schreiben. Zum Beispiel 2 Uhr CST gegen 2 Uhr CDT
Joe Phillips

1
Ja, das ist üblich: Wenn Sie einen (zivilen) Tagesdurchschnitt berechnen, müssen Sie mit Tagen von 23, 24 oder 25 Stunden fertig werden. Wenn Sie also einen Tag addieren, werden keine 24 Stunden addiert ! Zweitens versuchen Sie nicht, Ihren eigenen Zeitzonencode zu erstellen. Verwenden Sie nur die System-API. Vergessen Sie nicht, jedes bereitgestellte System zu aktualisieren, um die aktuelle Zeitzonendatenbank zu erhalten .
Alex

12

Für das Web sind die Regeln nicht so kompliziert ...

  • Verwenden Sie serverseitig UTC
  • Verwenden Sie auf der Clientseite Olson
    • Grund: UTC-Offsets sind nicht sommerzeitsicher (z. B. ist New York ein Teil des Jahres EST (UTC - 5 Stunden), der Rest des Jahres EDT (UTC - 4 Stunden)).
    • Für die clientseitige Zeitzonenbestimmung haben Sie zwei Möglichkeiten:

Der Rest ist nur eine UTC / lokale Konvertierung unter Verwendung Ihrer serverseitigen Datetime-Bibliotheken. Gut zu gehen ...


2
Dies ist ein guter Rat als Ausgangspunkt, hängt jedoch vollständig von der Anwendung ab. Dies mag für eine freundliche Website in Ordnung sein, aber wenn Ihre Bewerbung einen rechtlichen / gerichtlichen / finanziellen Aspekt hat, über den jemand klagen könnte (ich habe an mehreren gearbeitet), ist dies eine übermäßige Vereinfachung, da es verschiedene Arten von " Zeit ', wie an anderer Stelle auf dieser Seite angegeben.
DavidWalley

12

Wenn es um Anwendungen geht, die auf einem Server ausgeführt werden , einschließlich Websites und anderer Back-End-Dienste, sollte die Zeitzoneneinstellung des Servers von der Anwendung ignoriert werden.

Es wird allgemein empfohlen, die Zeitzone des Servers auf UTC einzustellen. Dies ist in der Tat eine gute bewährte Methode, dient jedoch als Pflaster für Anwendungen, die nicht anderen bewährten Methoden folgen. Beispielsweise schreibt ein Dienst möglicherweise in Protokolldateien mit lokalen Zeitstempeln anstelle von UTC-basierten Zeitstempeln, wodurch während des Fallback-Übergangs zur Sommerzeit Mehrdeutigkeiten entstehen. Wenn Sie die Zeitzone des Servers auf UTC einstellen , wird diese Anwendung behoben . Die eigentliche Lösung wäre jedoch, dass die Anwendung zunächst mit UTC protokolliert.

Serverseitiger Code, einschließlich Websites, sollte niemals erwarten , dass die lokale Zeitzone des Servers etwas Besonderes ist.

In einigen Sprachen kann sich die lokale Zeitzone leicht in den Anwendungscode einschleichen. Beispielsweise wird die DateTime.ToUniversalTimeMethode in .NET von der lokalen Zeitzone in UTC konvertiert , und die DateTime.NowEigenschaft gibt die aktuelle Zeit in der lokalen Zeitzone zurück. Auch dieDate Konstruktor in JavaScript die lokale Zeitzone des Computers. Es gibt viele andere Beispiele dafür. Es ist wichtig, die defensive Programmierung zu üben und jeglichen Code zu vermeiden, der die lokale Zeitzoneneinstellung des Computers verwendet.

Reservieren Sie mithilfe der lokalen Zeitzone für clientseitigen Code, z. B. Desktopanwendungen, mobile Anwendungen und clientseitiges JavaScript.


11

Halten Sie Ihre Server auf UTC eingestellt und stellen Sie sicher, dass sie alle für ntp oder gleichwertig konfiguriert sind.

UTC vermeidet Probleme mit der Sommerzeit, und nicht synchronisierte Server können zu unvorhersehbaren Ergebnissen führen, deren Diagnose eine Weile dauert.


9

Seien Sie vorsichtig, wenn Sie mit Zeitstempeln umgehen, die im FAT32-Dateisystem gespeichert sind - diese werden immer in lokalen Zeitkoordinaten beibehalten (einschließlich Sommerzeit - siehe msdn-Artikel ). Wurde daran verbrannt.


Toller Punkt. NTFS hat dieses Problem nicht, aber einige Leute verwenden immer noch FAT32 - insbesondere auf USB-Sticks.
Matt Johnson-Pint

7

Stellen Sie außerdem sicher, dass auf den Servern der aktuelle Sommerzeit-Patch angewendet wird.

Wir hatten letztes Jahr eine Situation, in der unsere Zeiten für nordamerikanische Benutzer drei Wochen lang konstant um eine Stunde abgelaufen waren, obwohl wir ein UTC-basiertes System verwendeten.

Es stellte sich am Ende heraus, dass es die Server waren. Sie brauchten lediglich einen aktuellen Patch ( Windows Server 2003 ).


6

PHP- DateTimeZone::listAbbreviations()Ausgabe

Diese PHP-Methode gibt ein assoziatives Array zurück, das einige "Haupt" -Zeitzonen (wie CEST) enthält, die für sich genommen spezifischere "geografische" Zeitzonen (wie Europa / Amsterdam) enthalten.

Wenn Sie diese Zeitzonen und ihre Offset- / Sommerzeitinformationen verwenden, ist es äußerst wichtig, Folgendes zu beachten:

Es scheint, dass alle unterschiedlichen Offset- / DST-Konfigurationen (einschließlich historischer Konfigurationen) jeder Zeitzone enthalten sind!

Zum Beispiel kann Europa / Amsterdam sechsmal in der Ausgabe dieser Funktion gefunden werden. Zwei Vorkommen (Offset 1172/4772) werden für die Amsterdamer Zeit bis 1937 verwendet; zwei (1200/4800) sind für die Zeit, die zwischen 1937 und 1940 verwendet wurde; und zwei (3600/4800) sind für die seit 1940 verwendete Zeit.

Daher können Sie sich nicht darauf verlassen, dass die von dieser Funktion zurückgegebenen Offset- / Sommerzeitinformationen aktuell korrekt sind / verwendet werden!

Wenn Sie den aktuellen Offset / die aktuelle Sommerzeit einer bestimmten Zeitzone wissen möchten, müssen Sie Folgendes tun:

<?php
$now = new DateTime(null, new DateTimeZone('Europe/Amsterdam'));
echo $now->getOffset();
?>

5

Wenn Sie Datenbanksysteme warten, auf denen die Sommerzeit aktiv ist, prüfen Sie sorgfältig, ob sie während des Übergangs im Herbst heruntergefahren werden müssen. Mandy DBS (oder auch andere Systeme) mögen es nicht, denselben Punkt in (lokaler) Zeit zweimal zu übergeben. Genau das passiert, wenn Sie die Uhr im Herbst zurückdrehen. SAP hat dies mit einer (meiner Meinung nach wirklich netten) Problemumgehung gelöst - anstatt die Uhr zurückzudrehen, ließ man die interne Uhr einfach zwei Stunden lang mit der halben Geschwindigkeit laufen ...


4

Verwenden Sie das .NET Framework ? Wenn ja, möchte ich Ihnen den DateTimeOffset- Typ vorstellen , der mit .NET 3.5 hinzugefügt wurde.

Diese Struktur enthält sowohl a DateTimeals auch einen Offset ( TimeSpan), der die Differenz zwischen DateTimeOffsetDatum und Uhrzeit der Instanz und der koordinierten Weltzeit (UTC) angibt .

  • Die DateTimeOffset.Nowstatische Methode gibt eine DateTimeOffset Instanz zurück, die aus der aktuellen (lokalen) Zeit und dem lokalen Offset besteht (wie in den regionalen Informationen des Betriebssystems definiert).

  • Die DateTimeOffset.UtcNowstatische Methode gibt eine DateTimeOffsetInstanz zurück, die aus der aktuellen Zeit in UTC besteht (als wären Sie in Greenwich).

Andere hilfreiche Typen sind die Klassen TimeZone und TimeZoneInfo .


Dies ist keine Lösung für das vorgestellte Problem.
Caradrye


4

Geschäftsregeln sollten immer in ziviler Zeit funktionieren (es sei denn, es gibt Gesetze, die etwas anderes vorschreiben). Seien Sie sich bewusst, dass bürgerliche Zeit ein Chaos ist, aber es ist das, was die Leute benutzen, also ist es das, was wichtig ist.

Bewahren Sie Zeitstempel intern in einer Zeitspanne von Sekunden auf. Die Epoche spielt keine besondere Rolle (ich bevorzuge die Unix-Epoche ), aber sie macht die Dinge einfacher als die Alternative. Stellen Sie sich vor, dass Schaltsekunden nur existieren, wenn Sie etwas tun, das sie wirklich benötigt (z. B. Satellitenortung). Die Zuordnung zwischen Zeitstempeln und angezeigter Zeit ist der einzige Punkt, an dem DST- Regeln angewendet werden sollten. Die Regeln ändern sich häufig (auf globaler Ebene mehrmals im Jahr; beschuldigen Sie Politiker), daher sollten Sie sicherstellen, dass Sie das Mapping nicht fest codieren. Olsons TZ-Datenbank ist von unschätzbarem Wert.


3
Das Problem hierbei ist, dass die bürgerliche Zeit (auch als Kalenderzeit bezeichnet) einen einzelnen Moment nicht richtig darstellt. Wenn Sie den Ansatz der Sekunden von der Epoche wählen, werden Sie dann wirklich jeden Moment berücksichtigen, der für Sommerzeitübergänge übersprungen oder zurückgespult wurde? Wahrscheinlich nicht. Die Epochenbasis funktioniert nur gegen UTC oder eine andere feste Momentanreferenz.
Matt Johnson-Pint

@ MattJohnson Daher der Teil "Geschäftsregeln". Wenn die Regeln besagen, dass etwas um 2:30 Uhr morgens (oder zu welcher Zeit auch immer) passiert, passiert es zweimal an einem Tag im Jahr und nie an einem Tag im Jahr. Das erwartet der Kunde wenn er die Regel nicht klarstellt.
user253751

Es kann sehr schwierig sein, interne Zeitstempel in der Zivilzeit zu halten. Wenn man es als Sekunden hält, seit eine Epoche noch schwieriger ist, würde ich sagen, geradezu gefährlich. Ich bin mir sicher, dass es Leute gibt, die das tun, und es könnte möglich sein, dass es die meiste Zeit richtig funktioniert, wenn Sie sehr vorsichtig sind, aber es kann nicht als Best Practice oder allgemeine Empfehlung angesehen werden.
Steve Summit

2

Ich wollte nur auf zwei Dinge hinweisen, die ungenau oder zumindest verwirrend erscheinen:

Behalten Sie die Zeit immer nach einem einheitlichen Standard bei, der nicht von der Sommerzeit beeinflusst wird. GMT und UTC wurden von verschiedenen Personen erwähnt, obwohl UTC am häufigsten erwähnt zu werden scheint.

Für (fast) alle praktischen Computerzwecke ist UTC tatsächlich GMT. Wenn Sie keine Zeitstempel mit einem Bruchteil einer Sekunde sehen, handelt es sich um GMT, wodurch diese Unterscheidung überflüssig wird.

Schließen Sie den lokalen Zeitversatz unverändert (einschließlich des Sommerzeitversatzes) ein, wenn Sie Zeitstempel speichern.

Ein Zeitstempel wird immer in GMT dargestellt und hat daher keinen Versatz.


1
Mit dem lokalen Zeitversatz können Sie die ursprüngliche "Wandzeit" des Ereignisses wiederherstellen. Wenn Sie dieses zusätzliche Feld nicht speichern, gehen diese Daten verloren.
Nogridbag

Ja, außer dass UTC- und GMT-Offsets invers sind. Zum Beispiel ist UTC-0700 dasselbe wie GMT + 0700. Eigentlich sollte heutzutage alles, was digital ist, UTC verwenden.
Matt Johnson-Pint

1
@Matt: Sind Sie sicher, dass UTC- und GMT-Offsets invers sind? wo kann ich das nachlesen
Reto Höhener

Eigentlich glaube ich, dass ich vorher falsch lag. GMT und UTC werden selbst nicht invertiert. Es gibt Implementierungen, die sie umgekehrt anzeigen, wie z. B. die IANA / Olson / TZDB-Datenbank. Siehe hier . Ein weiterer Bereich, in dem Offsets umgekehrt angezeigt werden, ist die Funktion getTimezoneOffset () von Javascript.
Matt Johnson-Pint

@ MattJohnson: Das sind Hacks und sollten abgeschafft werden.
Alix Axel

2

Hier ist meine Erfahrung: -

(Benötigt keine Bibliothek eines Drittanbieters)

  • Speichern Sie auf der Serverseite die Zeiten im UTC-Format, sodass alle Datums- / Zeitwerte in der Datenbank in einem einzigen Standard enthalten sind, unabhängig vom Standort der Benutzer, Server, Zeitzonen oder der Sommerzeit.
  • Auf der UI-Ebene oder in E-Mails, die an den Benutzer gesendet werden, müssen Sie die Zeiten nach Benutzer anzeigen. In diesem Fall muss der Zeitzonenversatz des Benutzers vorhanden sein, damit Sie diesen Versatz zum UTC-Wert Ihrer Datenbank hinzufügen können, was zur Ortszeit des Benutzers führt. Sie können entweder den Zeitzonenversatz des Benutzers bei der Anmeldung verwenden oder ihn auf Web- und mobilen Plattformen automatisch erkennen. Für Websites ist die JavaScript-Methode getTimezoneOffset () seit Version 1.0 ein Standard und mit allen Browsern kompatibel. (Ref: http://www.w3schools.com/jsref/jsref_getTimezoneOffset.asp )

Dies funktioniert nicht, wenn Sie Änderungen der Sommerzeit berücksichtigen. getTimezoneOffsetGibt den Offset für das Datum und die Uhrzeit zurück, zu der Sie ihn aufrufen. Dieser Versatz kann sich ändern, wenn eine Zeitzone in die Sommerzeit oder aus dieser heraus wechselt. Siehe "Zeitzone! = Versatz" im Zeitzonen-Tag-Wiki .
Matt Johnson-Pint

1
Wenn Sie einen Alarm wie "etwas um 10:00 Uhr tun" speichern möchten, können Sie ihn aufgrund von Sommerzeitverschiebungen nicht in UTC speichern. Sie müssen es relativ zur Ortszeit speichern.
Alex

2

Tom Scotts Video über Zeitzonen auf YouTube im Computerphile-Kanal enthält auch eine schöne und unterhaltsame Beschreibung des Themas. Beispiele beinhalten:

  • Samoa (eine Insel im Pazifik) verschiebt seine Zeitzone um 24 Stunden, um den Handel mit Australien und Neuseeland zu vereinfachen.
  • Westufer , wo 2 Bevölkerungsgruppen unterschiedlichen Zeitzonen folgen,
  • Das 18. Jahrhundert wechselt vom julianischen zum gregorianischen Kalender (was im 20. Jahrhundert in Russland geschah).

1

Tatsächlich exportiert kernel32.dll SystemTimeToTzSpecificLocation nicht. Es werden jedoch die folgenden zwei exportiert: SystemTimeToTzSpecificLocalTime und TzSpecificLocalTimeToSystemTime ...


1

Verlassen Sie sich niemals nur auf Konstrukteure wie

 new DateTime(int year, int month, int day, int hour, int minute, TimeZone timezone)

Sie können Ausnahmen auslösen, wenn aufgrund der Sommerzeit eine bestimmte Datums- / Uhrzeit nicht vorhanden ist. Erstellen Sie stattdessen Ihre eigenen Methoden zum Erstellen solcher Daten. Fangen Sie in ihnen alle Ausnahmen ab, die aufgrund der Sommerzeit auftreten, und passen Sie die benötigte Zeit mit dem Übergangsversatz an. Die Sommerzeit kann je nach Zeitzone zu unterschiedlichen Daten und zu unterschiedlichen Zeiten (für Brasilien sogar um Mitternacht) auftreten.


1

Nur ein Beispiel, um zu beweisen, dass die Bearbeitungszeit das beschriebene große Durcheinander ist und dass Sie niemals selbstgefällig sein können. An mehreren Stellen auf dieser Seite wurden Schaltsekunden ignoriert.

Vor einigen Jahren verwendete das Android-Betriebssystem GPS-Satelliten, um eine UTC-Zeitreferenz zu erhalten, ignorierte jedoch die Tatsache, dass GPS-Satelliten keine Schaltsekunden verwenden. Niemand bemerkte es, bis es an Silvester Verwirrung gab, als die Apple-Telefonbenutzer und Android-Telefonbenutzer ihre Countdowns im Abstand von etwa 15 Sekunden durchführten.

Ich denke, es wurde inzwischen behoben, aber Sie wissen nie, wann diese "kleinen Details" zurückkommen werden, um Sie zu verfolgen.


1
  • Speichern Sie niemals die Ortszeit ohne ihren UTC-Versatz (oder einen Verweis auf die Zeitzone). Beispiele dafür, wie dies nicht getan werden soll, sind FAT32 und struct tm in C.¹
  • Verstehen Sie, dass eine Zeitzone eine Kombination aus ist
    • eine Reihe von UTC-Offsets (z. B. +0100 im Winter, +0200 im Sommer)
    • Regeln für den Zeitpunkt der Umstellung (die sich im Laufe der Zeit ändern können: In den neunziger Jahren hat die EU beispielsweise die Umstellung auf die letzten Sonntage im März und Oktober um 02:00 Uhr Standardzeit / 03:00 Uhr MESZ harmonisiert, zuvor war dies anders zwischen den Mitgliedstaaten).

¹ Einige Implementierungen von struct tmdo speichern den UTC-Offset, dies hat es jedoch nicht zum Standard gemacht.


-4

Beim Umgang mit Datenbanken (insbesondere MySQL , dies gilt jedoch für die meisten Datenbanken) fiel es mir schwer, UTC zu speichern.

  • Datenbanken arbeiten normalerweise standardmäßig mit der Datumszeit des Servers (dh CURRENT_TIMESTAMP).
  • Möglicherweise können Sie die Server-Zeitzone nicht ändern.
  • Selbst wenn Sie die Zeitzone ändern können, verfügen Sie möglicherweise über Code von Drittanbietern, der erwartet, dass die Server-Zeitzone lokal ist.

Ich fand es einfacher, nur die Server-Datumszeit in der Datenbank zu speichern und dann die gespeicherte Datumszeit in den SQL-Anweisungen wieder in UTC (dh UNIX_TIMESTAMP ()) konvertieren zu lassen. Danach können Sie die datetime als UTC in Ihrem Code verwenden.

Wenn Sie 100% Kontrolle über den Server und den gesamten Code haben, ist es wahrscheinlich besser, die Server-Zeitzone auf UTC zu ändern.


Die Ortszeit (die Serverzeit) kann bei Sommerzeitübergängen im "Fallback" -Stil nicht eindeutig sein. Es ist nicht zuverlässig zu verwenden, wie Sie beschrieben haben. Es kann mehr als eine UTC-Zeit geben, die die Ortszeit des Servers darstellen könnte.
Matt Johnson-Pint

Die Ortszeit ist vollkommen in Ordnung, wenn sich der Server in einer vernünftigen Zeitzone befindet, dh in einer Zeitzone, in der keine Sommerzeit ausgeführt wird.
Sayap
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.