2012-09-01 10 views
5

Meine Anforderung hier ist ziemlich Standard; Ich muss Benutzern erlauben, ihre aktuelle Zeitzone auszuwählen und sie für ihr Konto zu speichern. Ich werde dann diesen Wert verwenden, um gespeicherte DateTime Werte zu einer lokalisierten Zeit zu konvertieren.Speichern eines Benutzers Zeitzone Präferenz

Mein aktuelles Denken ist, dass ich die Benutzer erlaubt, einen .NET-TimeZoneInfo.Id aus einer Liste auswählen (in der DB gehalten freundlichere Beschreibungen zu ermöglichen, aber welches unter Verwendung TimeZoneInfo.GetSystemTimeZones()) - Ich werde dann diesen Wert verwenden, um die entsprechende TimeZoneInfo Instanz zurückzukehren Verwenden Sie TimeZoneInfo.FindSystemTimeZoneById() und führen Sie die Konvertierung durch. Das Hauptproblem, das ich hier sehe, ist, dass TimeZoneInfo.Id ist ein Wert in der Registrierung gehalten und ist keine "Standard" Id (im Vergleich zu Olson zum Beispiel). Daher ist es möglich, dass Server-Updates/Migrationen die gespeicherten IDs vollständig ungültig machen und die Konvertierungen unterbrechen.

Kurz gesagt - ist dieser Ansatz gültig/sicher? Wenn nicht, gibt es eine bessere Möglichkeit, die Zeitzonenpräferenz eines Benutzers zu speichern, während auch die Sommerzeit usw. ohne zusätzliche Logik verarbeitet wird?

+0

Haben Sie ['DateTimeOffset'] (http://msdn.microsoft.com/en-us/library/system.datetimeoffset.aspx) angeschaut? Oder ['NodaTime'] (http://code.google.com/p/noda-time/)? – Oded

+0

Related: http://StackOverflow.com/q/2532729/1583 – Oded

+1

@Oded Das Problem mit DateTimeOffset ist, dass es nicht Day Light Savings bewusst ist – Paparazzi

Antwort

8

Ich habe gerade diese alte unbeantwortete Frage gefunden, also dachte ich, ich sollte einen Stich machen.

Kurz gesagt - ist dieser Ansatz gültig/sicher?

Es hängt alles davon ab, was Sie mit ihnen vorhaben.

Wenn Sie es nur im serverseitigen Code verwenden, dann ja. Sie speichern einfach die Id der Zeitzone und zeigen dem Benutzer die entsprechende DisplayName. FindSystemTimeZoneById und GetSystemTimeZones sind dafür vollkommen gültig.

Beachten Sie, dass die Werte Id immer gleich sind - die Eigenschaften DisplayName unterscheiden sich je nach der Sprache des Windows-Betriebssystems, auf dem Sie den Code ausführen. Die Implementierung ist nicht Kultur bewusst, so nur die Einstellung einer anderen Zielkultur in. NET wird die DisplayName Zeichenfolge nicht ändern.

Die Datensätze in der Microsoft Windows-Zeitzonendatenbank sind einigermaßen stabil und werden über Windows Update aktualisiert. Einige der Informationen stammen aus der Registrierung, aber die lokalisierten Ressourcenzeichenfolgen stammen aus tzres.dll. Natürlich ist all das von Ihnen durch TimeZoneInfo und verwandte Klassen versteckt.

Wenn Sie diese Werte der Zeitzone Id jedoch an andere Systeme weitergeben, sollten Sie aufpassen. Es gibt einige Variationen mit früheren Versionen von Windows. Zum Beispiel weiß ich, dass die Display-Namen für alle sagen "GMT" in ihnen, und jetzt richtiger sagen "UTC". Die Id Werte sind gleich, aber wer genau weiß, was sonst nicht konsistent ist. Vor allem, wenn der Zielcomputer nicht die gleichen Windows-Updates erhalten hat wie Sie. Übrigens - die Updates sind angekündigt here.

Sie sollten auch ein paar Dinge über die Windows-Zeitzonen-Datenbank kennen:

  • Es ist nicht in der Lage mehr als zwei darstellt DST Übergänge pro Kalenderjahr. Zum Beispiel - in 2010, Cairo, Egypt had four transitions. Microsoft gab a hotfix aus, aber das machte nur eine Kompromittierung, keine historisch genaue. Es gibt andere Zonen mit solchen historischen Änderungen, die nicht korrekt dargestellt werden können.

  • Einige Dinge haben sich zwischen Windows XP/2003 und Vista/2008 geändert. Es gibt einige wirklich gute Informationen über diese here, zusammen mit vielen Details darüber, wie die Registrierung verwendet wird.

  • Microsoft ist der nur Hauptakteur mit ihrer eigenen Zeitzone-Datenbank. Der Rest der Welt verwendet die IANA/Olson database. Dies führt zu Interoperabilitätsproblemen. Ich habe eine anständige Beschreibung davon in the timezone tag wiki.

Sie auch, dass TimeZoneInfo untrennbar wissen sollten den DateTime und DateTimeOffset Klassen verknüpft ist. Diese haben ihre eigenen Macken. DateTimeOffset ist etwas brauchbar, aber DateTime ist mit Nuancen gespickt. Lesen:

A weit bessere Lösung zu Datum und Uhrzeit in .Net ist NodaTime zu verwenden. Diese Bibliothek implementiert beide Zeitzone-Datenbanken, einschließlich der CLDR-Zuordnungen zwischen ihnen. Es bietet auch eine viel sicherere API, die Sie nicht in Schwierigkeiten geraten lässt. Es kann ein bisschen neu lernen, aber bevor Sie es wissen, werden Sie Klassen wie LocalDateTime, ZonedDateTime, OffsetDateTime und Instant verwenden.

Sie haben immer noch das Problem, dass die Zeitzonendatenbank häufig aktualisiert wird, da wir die Zeiteinstellungsregeln den Politikern überlassen. Aber the TZDB folks machen einen ziemlich guten Job, die Datenbank historisch korrekt zu halten und Aliase/Links zu liefern, wenn sich Zonennamen ändern. Sie können eine Liste der tz-Namen here sehen.

Auch, wenn Sie mit NodaTime gehen, können Sie entweder mit der Kopie der TZDB in der Verteilung kompiliert bleiben, oder Sie können Ihre eigene Kopie mit Ihrer Anwendung versenden. Sie könnten (theoretisch) Ihren eigenen Code schreiben, um die neueste Version von IANA herunter zu laden und Ihre Anwendung auf dem neuesten Stand zu halten - alles ohne auf das Host-Betriebssystem angewiesen zu sein.

+0

Das ganze timezoneinfo.ID Ding macht keinen Sinn. Es wird erwartet, dass die ID eine Kennung ist, die einem ISO-Standardweg folgt. Ich habe jedoch herausgefunden, dass 'FindSystemTimeZoneById' in verschiedenen Windows-Versionen nicht korrekt funktioniert.In einer Version ist die zurückgegebene Zeichenfolge in Kleinbuchstaben und die andere in camel case. Um die Sache noch schlimmer zu machen, wird in FindSystemTimeZoneById nicht zwischen Groß- und Kleinschreibung unterschieden. Stelle dir das vor! – Rajiv

+0

@Rajiv - Es gibt keine ISO-Standards für Zeitzonen. IANA/Olson-Identifikatoren (oben erwähnt) sind das Nächste, was wir zu einem Standard haben. Was die Windows-IDs betrifft, habe ich noch nie solche gefunden, die in der unteren Reihe liegen, es sei denn, sie wurden von etwas anderem gemangelt. Wie oben erwähnt, sollten die IDs systemweit konsistent sein, es sei denn, Sie sprechen über eine neu eingeführte Zeitzone, die auf einem System installiert wurde, aber nicht auf einem anderen. Beispiel: [KB3093504] (https://support.microsoft.com/en-us/kb/3093503) führte in einem Hotfix "Nordkorea-Standardzeit" ein. –

Verwandte Themen