Mein lokaler Entwicklungsserver befindet sich im Nahen Osten, aber mein Produktionsserver befindet sich in Großbritannien.
Ich muss dem Benutzer das Datum in seiner Zeitzone anzeigen. Wenn sich zum Beispiel ein Benutzer in Saudi-Arabien befindet, muss ich die Zeit gemäß dem Saudi-Arabien-Format anzeigen.
Soll ich eine neue Datenbanktabelle mit dem Namen TimeZone erstellen und die Uhrzeit in UTC speichern?
sql-server
sql-server-2008
timezone
user960567
quelle
quelle
Antworten:
Leider gibt es dafür keine schnelle Lösung. Die Internationalisierung einer Anwendung sollte Teil der allerersten Designdiskussionen sein, da sie den Kern vieler verschiedener Bereiche betrifft, einschließlich Datums- / Uhrzeitvergleiche und Ausgabeformatierung.
Auf jeden Fall ist es wichtig, die Zeitzoneninformationen mit der Zeit zu speichern, um den Überblick über Doing It Right zu behalten . Mit anderen Worten realisieren, dass das Datum / Zeit
20130407 14:50
ist sinnlos , ohne entweder (a) mit der dann aktuellen UTC der Zeitzone versetzt (Anmerkung 1) , oder (b) sichergestellt wird, dass alle Logik dieser Werte zuerst wandelt in einem bestimmten festgelegten Offset Einfügen ( höchstwahrscheinlich 0). Ohne diese beiden Dinge sind zwei angegebene Zeitwerte nicht vergleichbar und die Daten sind fehlerhaft . (Die letztere Methode spielt übrigens mit dem Feuer (Anmerkung 2) ; tun Sie das nicht.)In SQL Server 2008+ können Sie den Versatz mit der Zeit direkt mithilfe des
datetimeoffset
Datentyps speichern. (Der Vollständigkeit halber habe ich 2005 und früher eine zweite Spalte hinzugefügt, um den aktuellen UTC-Offset-Wert (in Minuten) zu speichern.)Dies erleichtert eine Desktop-Anwendung, da diese Plattformen normalerweise über Mechanismen verfügen, mit denen Datum / Zeit + Zeitzone automatisch in eine Ortszeit konvertiert und dann entsprechend den regionalen Einstellungen des Benutzers für die Ausgabe formatiert werden.
Für das Web, bei dem es sich um eine von Natur aus getrennte Architektur handelt, ist es auch bei ordnungsgemäß eingerichteten Back-End-Daten komplexer, da Sie Informationen zum Client benötigen, um die Konvertierung und / oder Formatierung durchführen zu können. Dies erfolgt in der Regel über Benutzereinstellungen (die Anwendung konvertiert / formatiert Dinge vor der Ausgabe) oder einfach durch Anzeigen von Dingen mit demselben festen Format und Zeitzonenversatz für alle (wie dies derzeit auf der Stack Exchange-Plattform der Fall ist).
Sie können feststellen, dass die Einrichtung der Back-End-Daten sehr schnell kompliziert und schwierig wird. Ich würde nicht empfehlen, einen dieser Pfade zu beschreiten, da Sie später einfach mehr Probleme haben werden.
Anmerkung 1:
Der UTC-Versatz einer Zeitzone ist nicht festgelegt: Berücksichtigen Sie die Sommerzeit, wenn der UTC-Versatz einer Zone um plus oder minus eine Stunde variiert. Auch die Sommerzeitdaten der Zonen variieren regelmäßig. Die Verwendung von
datetimeoffset
(oder einer Kombination auslocal time
undUTC offset at that time
) führt zu einer maximalen Wiederherstellung von Informationen.Anmerkung 2:
Es geht darum, Dateneingaben zu steuern. Es gibt zwar keine narrensichere Möglichkeit, eingehende Werte zu validieren, es ist jedoch besser, einen einfachen Standard zu erzwingen, der keine Berechnungen umfasst. Wenn eine öffentliche API einen Datentyp erwartet, der einen Offset enthält, ist diese Anforderung für den Aufrufer klar.
Wenn dies nicht der Fall ist, muss sich der Aufrufer auf die Dokumentation verlassen (wenn er sie liest), oder die Berechnung wird falsch durchgeführt usw. Es gibt weniger Fehler- / Fehlermodi, wenn ein Offset erforderlich ist, insbesondere für ein verteiltes System ( oder auch nur Web / Datenbank auf separaten Servern (wie hier der Fall).
Das Speichern des Offsets tötet ohnehin zwei Fliegen mit einer Klappe; und selbst wenn das jetzt nicht benötigt wird , wird die möglichkeit später bei bedarf zur verfügung gestellt. Zwar nimmt es mehr Speicherplatz in Anspruch, aber ich denke, es lohnt sich, dies in Kauf zu nehmen, da die Daten verloren gehen, wenn sie überhaupt nicht aufgezeichnet werden.
quelle
datetimeoffset
bedeutet "Dies ist die Ortszeit des Benutzers / Computers, zu der das Ereignis aufgetreten ist" - wir müssen nicht wissen, ob die Sommerzeit wirksam war oder nicht, da der angegebene UTC-Offset immer vorhanden ist (eingebettet in dendatetimeoffset
Wert).Ich habe eine umfassende Lösung für die Zeitzonenkonvertierung in SQL Server entwickelt. Siehe SQL Server-Zeitzonenunterstützung auf GitHub .
Konvertierungen zwischen Zeitzonen sowie von und nach UTC, einschließlich der Sommerzeit, werden ordnungsgemäß verarbeitet.
Es ähnelt im Konzept der in der Antwort von adss beschriebenen "T-SQL Toolbox" -Lösung, verwendet jedoch die gängigeren IANA / Olson / TZDB-Zeitzonen anstelle der von Microsoft und enthält Dienstprogramme, mit denen die Daten als neue Versionen von beibehalten werden TZDB kommt raus.
Anwendungsbeispiel (zur Beantwortung des OP):
Weitere APIs und ausführliche Erklärungen finden Sie in der Readme-Datei auf GitHub .
Beachten Sie außerdem, dass dies eine UDF-basierte Lösung ist, die nicht auf Leistung als primäres Ziel ausgelegt ist. Es wäre immer noch besser, wenn diese Funktionalität in SQL Server integriert wäre, ähnlich wie die
CONVERT_TZ
Funktion in Oracle und MySQL vorhanden ist.quelle
SQL Server nahm ab 2005 Änderungen vor, bei denen die interne Zeitzone in UTC gespeichert wird. Dies war hauptsächlich auf die Geo-Replikation und HA-Projektoren zurückzuführen, die den Protokollversand umfassten, und da die Protokollversandzeiten in verschiedenen Zeitzonen gespeichert waren, war es für die alte Methode unmöglich, sie wiederherzustellen.
Wenn Sie also alles intern in UTC-Zeit speichern, funktioniert SQL Server global einwandfrei. Dies ist einer der Gründe, warum die Sommerzeit in Windows ein Problem ist, da andere MS-Produkte wie Outlook das Datum und die Uhrzeit auch intern als UTC speichern und einen Offset erstellen, der gepatcht werden muss.
Ich arbeite in einem Unternehmen, in dem Tausende von Servern (allerdings nicht MS SQL Server, sondern alle Arten von Servern) auf der ganzen Welt verteilt sind, und wenn wir nicht ausdrücklich alles auf UTC-Basis erzwingen würden, würden wir alle verrückt werden sehr schnell.
quelle
Ich habe das „T-SQL Toolbox“ -Projekt für Codeplex entwickelt und veröffentlicht , um allen zu helfen, die mit der Verarbeitung von Datum und Uhrzeit in SQL Server zu kämpfen haben. Es ist Open Source und völlig kostenlos zu benutzen.
Es bietet einfache UDFs für die Datums- und Uhrzeitkonvertierung unter Verwendung von einfachem T-SQL mit zusätzlichen Konfigurationstabellen.
In Ihrem Beispiel können Sie das folgende Beispiel verwenden:
Dadurch wird der konvertierte Datums- / Uhrzeitwert für Ihren Benutzer zurückgegeben.
Eine Liste aller unterstützten Zeitzonen finden Sie in der Tabelle "DateTimeUtil.Timezone", die ebenfalls in der T-SQL Toolbox-Datenbank enthalten ist.
quelle
Ich vermisse vielleicht etwas Offensichtliches, aber wenn Sie nur das Datum in der Zeitzone und im Sprachformat des Benutzers anzeigen möchten, ist es am einfachsten, die Datumsangaben immer in UTC in der Datenbank zu speichern und die Client-Anwendung von UTC nach lokal konvertieren zu lassen Verwenden Sie die regionalen Benutzereinstellungen, um das Datum entsprechend zu formatieren.
quelle