Bewährte Methode zum Speichern von DateTime basierend auf TimeZone

16

Entwicklung einer Webanwendung, mit der der Benutzer einen Termin basierend auf seiner Zeitzone planen kann. Und ich speichere die vom Benutzer geplante Datumszeit als Server Datumszeit im Datenbankfeld. Beim Anzeigen von Zeitplaninformationen wurde der Wert aus der Datenbank abgerufen und in die Benutzer-Zeitzone konvertiert. Verarbeitung in der Codebasis Ich konvertiere die DateTime basierend auf der Benutzer-Zeitzone. Bitte schlagen Sie vor, dass dies eine bewährte Methode ist oder eine einfache Möglichkeit besteht.

user46506
quelle

Antworten:

33

Willkommen bei einem der schwierigsten Probleme bei der nicht-rechnergestützten Programmierung - die korrekte Darstellung von Datum und Uhrzeit für Endbenutzer.

Realistisch gesehen sollten Zeitstempel in einer festen Einzelrepräsentation gespeichert werden, unabhängig davon, wie sie interpretiert werden, da Sie unabhängig von Ihrer Anstrengung immer mehrdeutige Fälle haben und sie ohne eine feste Repräsentation nicht lösen können. Und Sie haben einen der schlimmsten Anwendungsfälle ausgewählt - das Planen eines Termins. Der einzig schlimmere allgemeine Anwendungsfall ist der Flugverkehr, bei dem eine Reise in einer Zeitzone beginnen und in einer anderen enden kann, möglicherweise zu einer früheren Ortszeit.

Immer, immer, IMMER in UTC speichern und in der vom Benutzer bevorzugten oder explizit angegebenen Zeitzone anzeigen. Wenn möglich, teilen Sie dem Benutzer mit, in welcher Zeitzone er den Zeitstempel voraussichtlich eingibt ( z. B. mit einem expliziten Zeitzonenfeld und einer Vorbelegung mit der von ihm bevorzugten Zone).

Ross Patterson
quelle
1
+1. Und es ist flexibel. Mit einer gemeinsamen, konsistenten, universellen Standardreferenzzeit wird jede "Dereferenzierung" der lokalen Zone korrekt durchgeführt.
Radarbob
Tatsächlich ist das Planen eines Termins eines der wenigen Male, wenn Sie ihn möglicherweise nicht als UTC speichern: Wenn sich die DST-Regeln ändern (oder der Versatz von UTC), was passiert dann mit der Terminzeit? In den meisten Fällen möchten Sie, dass die Terminzeit lokal gleich bleibt, was bedeutet, dass sich der UTC-Wert ändert. Sie möchten höchstwahrscheinlich einen Wert für "TimeInTimeZone + TimeZone" speichern, von dem Sie UTC leicht ableiten können. Die zeitzonenübergreifende Planung (wie bei Fluggesellschaften) unterliegt Einschränkungen, die wahrscheinlich bedeuten, dass eine Kombination aus beiden verwendet wird.
Clockwork-Muse
1
Oh, es wird schlimmer. Ich treffe mich regelmäßig mit Kollegen in anderen Ländern, deren Zeitänderungsregeln von meinen abweichen. Wenn das passiert, was ist die richtige Antwort? Eigentlich kann kein Computer wissen :-(
Ross Patterson
3

Der einfachste Weg, mit Datums- und Uhrzeitinformationen umzugehen, hängt von den Anforderungen Ihrer Anwendung ab.

Wenn das Datum und die Uhrzeit vom Benutzer eingegeben werden und der Server diese Datums- / Uhrzeitinformationen nur zum Speichern in einer Datenbank verarbeitet und nicht erwartet, dass die eingegebene Uhrzeit an den Ort angepasst wird, an dem sie angezeigt werden (z. B.) Wenn der Benutzer "8:00 PM" eingegeben hat und es als "8:00 PM" angezeigt werden soll, unabhängig davon, wo auf der Welt es angezeigt wird), ist es die einfachste Möglichkeit, die Datums- und Uhrzeitangabe als Ortszeit ohne Zeitzonenangabe zu speichern.

Wenn der Server andererseits die eingegebene DateTime als Auslöser verwenden muss, oder wenn die Zeit korrekt an die aktuelle Zeitzone angepasst werden soll, ist es Ihre beste Option, die DateTime als UTC-Zeit zu speichern und lokal anzupassen Zeit (für den aktuellen Standort des Benutzers) jedes Mal, wenn Sie ihn aus der Datenbank lesen.

Bart van Ingen Schenau
quelle
-1 für "in lokaler Zeit speichern", +1 für "in UTC speichern".
Ross Patterson
@ RossPatterson: Können Sie Ihre "-1" für "Speichern in Ortszeit" erklären? Ich bin gespannt, warum es eine schlechte Idee sein sollte, wenn man die Bedingungen bedenkt, die ich damit angegeben habe.
Bart van Ingen Schenau
1
Beispielsweise bedeutet die Verwendung der benutzerlokalen Zeit, dass jeder Wert einem von mehreren Dutzend verschiedenen Datentypen entspricht. Das bedeutet, dass Sie keine Datenbankoperationen wie "TIMESTAMP> '2013-08-27T12: 00: 00'" durchführen können. Es bedeutet sogar, dass Sie nicht wissen können, wann und ob Sie die Sommerzeitumrechnung anwenden sollen.
Ross Patterson
@ RossPatterson: Danke. Ich bin damit einverstanden, dass die Ortszeit in den meisten Fällen nicht die richtige Lösung ist.
Bart van Ingen Schenau
2

Es ist wichtig, dass Sie nicht zwei verwandte Konzepte miteinander verschmelzen.

Wenn Sie einen tatsächlichen Zeitpunkt, dh eine bestimmte Uhrzeit an einem bestimmten Tag, bearbeiten, können Sie dies nur tun, indem Sie immer den universellen UTC-Zeitwert verwenden. Versuchen Sie niemals, diesen Wert als zeitzonenrelevanten Wert zu speichern. Wenn Sie einem Benutzer diesen Zeitwert anzeigen, konvertieren Sie immer zu diesem Zeitpunkt in die Benutzerzeitzone. (Und vergessen Sie nicht, dass sowohl Uhrzeit als auch Datum von der Zeitzone abhängen.)

Das andere Konzept ist das eines "Zeitausdrucks" wie "20:00 Uhr jeden Dienstag". Sie haben ausdrücklich erwähnt, dass Sie es Personen ermöglichen, Termine zu planen. Wenn Sie wiederkehrende Termine haben, benötigen Sie einen solchen Ausdruck. Ich kenne keine Standardausdruckssprache, aber was auch immer Sie verwenden, es wird relativ zur Zeitzone der Person sein, die es spezifiziert hat. Es ist am besten, dies explizit anzugeben, z. B. "20:00 Uhr jeden Dienstag in der pazifischen Zeitzone". Im Fall eines Zeitausdrucks speichern Sie diesen immer als Zeichenfolge und beziehen keine Systemzeitformate mit ein.

Sehen Sie mehr Diskussion über diese auf meinem Blog

AgilePro
quelle
1

Viele Antworten geben hier das Speichern als UTC an. Aber sei wirklich vorsichtig damit. Wenn Sie beispielsweise einen Termin um 12:00 Uhr planen, der Termin jedoch nach der Umstellung auf Sommerzeit stattfindet, was passiert dann? UTC speichert keine Informationen darüber, ob dst aktiv war, als der Termin gespeichert wurde. Viele große, bekannte Systeme haben diesen Fehler gemacht, bei dem ein Benutzer im Sommer um 9 Uhr morgens eine E-Mail sendet und im Winter die Sendezeit 8 Uhr morgens anzeigt, da die Rückrechnung von UTC davon abhängt, wann Sie die Datumszeit betrachten. Nicht an, wenn die Datums- / Uhrzeitangabe aufgezeichnet wurde.

Viel besser ist es anzunehmen, dass Ihr Benutzer die von ihm ausgewählten Zeiten immer haben möchte. Keine UTC-Konvertierung, keine Zeitkonvertierung, keine Zeitzoneninformationen, nichts. Genau das ist es, wenn Sie am 21. März 2016 von 08:00 bis 12:00 Uhr einen Termin vereinbaren. Verwenden Sie weder die Ortszeit noch die UTC-Zeit, sondern die nicht angegebene Zeit (in json hat dies weder z noch +, im Grunde genommen hat dies in .NET DateTime.Kind = DateTimeKind.Unspecified).

Wenn Ihr Anwendungsfall ist, dass Sie ein Unternehmen sind, das Besprechungen mit einer Person aus verschiedenen Zeitzonen abhält, und diese Informationen beispielsweise in einem Unternehmenskalender angezeigt werden sollen, können Benutzer jedoch die Uhrzeit in ihrer Zeitzone anzeigen wird komplizierter. Die Zeit muss für verschiedene Personen in verschiedenen Zeitzonen (Lieferant und Kunde) korrekt sein.

In diesen Fällen möchten Sie möglicherweise sogar aufzeichnen, wann der Termin in der Datenbank gespeichert wurde, in welcher Zeitzone und ob dies dst beinhaltet oder nicht. Auf diese Weise können Sie die Ortszeit immer auf etwas anderes zurückrechnen, entweder auf das, was jetzt wäre, oder auf das, was historisch beabsichtigt war. Weil Zeitzonen nicht statisch sind, wird die Sache noch komplizierter.

Zum Glück kommen hier Bibliotheken wie http://nodatime.org/ ins Spiel , die sehr zu empfehlen sind. Sie arbeiten viel konsequenter mit Daten. Selbst dann würde ich empfehlen, alle Ihre datetime-Variablen und -Logik in Ihre eigenen Wrapper zu packen und Schnittstellen zu verwenden, damit sie verspottet werden können, und dann können Sie die Logik später noch wechseln.

Arwin
quelle
Ich bin mit Ihren Schlussfolgerungen nicht ganz einverstanden, aber ein Treffen um 12.00 Uhr, das für eine Sommerzeitumstellung angesetzt ist, ist eine besondere Herausforderung, da ein wöchentliches Treffen um 12.00 Uhr mehrere Jahre in der Zukunft gebucht werden würde.
Bent
" Wenn Ihr Anwendungsfall natürlich ist, dass Sie ein Unternehmen sind, das Besprechungen mit einer Person aus verschiedenen Zeitzonen abhält, und diese Informationen beispielsweise in einem Unternehmenskalender angezeigt werden sollen, die Benutzer jedoch die Uhrzeit in ihrer Zeitzone anzeigen können, es wird komplizierter. "- das ist so ziemlich jedes unternehmen. Nur sehr wenige Unternehmen außerhalb Chinas und Indiens können zeitzonenübergreifende Termine ignorieren.
Ross Patterson
"Auf diese Weise können Sie die Ortszeit immer auf irgendetwas anderes zurückrechnen, entweder auf das, was es jetzt wäre oder auf das, was historisch beabsichtigt war. Denn Zeitzonen sind sehr viel nicht statisch, was die Dinge noch komplizierter macht. " Wenn Sie akzeptieren, dass Sie Berechnungen durchführen werden, müssen Sie wirklich eine einzige Darstellung für die Zeit auswählen. UTC, EST (aber nicht EST5EDT), IST, was auch immer. Es ist jedoch einfach nicht möglich, Werte basierend auf mehreren Zeitzonen im selben Feld zu haben und diese in legitimer Weise zu verarbeiten. Displayverarbeitung, klar. Aber das ist der einfache Teil.
Ross Patterson
Zumindest können Sie immer noch korrekt in UTC konvertieren. Sie können jederzeit nachträglich eine Berechnungstabelle oder einen Wert aus diesen Informationen erstellen. Aber du kannst niemals den anderen Weg gehen. Beachten Sie, dass SQL 2016 dies von Haus aus unterstützt, obwohl es sich leider immer noch auf die - zumindest historisch - nicht ganz korrekten Registrierungsdaten stützt - aber es ist eine weitere Verbesserung.
Arwin