Ich frage mich, wie man die Zeitzone eines DateTime-Objekts ändern kann, ohne den Wert tatsächlich zu ändern. Hier ist der Hintergrund ...
Ich habe eine ASP.NET MVC-Site auf AppHarbor gehostet und der Server hat seine Zeit auf UTC eingestellt. Wenn ich ein Formular von meiner Site übergebe, das einen Datetime-Wert enthält, sagen wir 17.09.2013, 4:00 Uhr, kommt es auf den Server mit diesem Wert. Aber dann, wenn ich das tue:
%Vor%... es hält es fälschlicherweise als die selbe Zeit (4 Uhr), weil der Server bereits in der UTC-Zeit ist. Nach dem Konvertieren in UTC und dem Speichern in der Datenbank ist der Datenbankwert 2013-09-17 04: 00: 00.000, wenn es wirklich 2013-09-17 08: 00: 00.000 sein sollte, da der Browser auf EST ist. Ich hatte gehofft, dass nach dem Senden des Formulars und dem Übergeben der Werte an die Controller-Aktion die Zeitzone von DateTime auf den Browser (EST) und nicht auf den Server-Host (UTC) gesetzt würde, was aber nicht passiert ist.
In jedem Fall stecke ich jetzt mit einem DateTime-Objekt fest, das den korrekten Datums- / Uhrzeitwert aber die falsche Zeitzone enthält, sodass ich es nicht korrekt in UTC umwandeln kann. Ich speichere die Zeitzone jedes Benutzers. Wenn es also eine Möglichkeit gibt, die Zeitzone für das DateTime-Objekt festzulegen, ohne den Wert tatsächlich zu ändern (TimeZoneInfo.ConvertTime kann nicht ausgeführt werden, weil der Wert geändert wird), könnte ich das haben der richtige Datum / Uhrzeit-Wert UND die richtige Zeitzone, dann könnte ich sicher Date.ToUniversalTime tun. Davon abgesehen habe ich nur gesehen, wie man die Art einer DateTime ändert, nicht die TimeZone, ohne ihren tatsächlichen Wert zu ändern.
Irgendwelche Ideen?
Eigentlich macht es genau das, was Sie von ihm verlangt haben. Aus der Sicht des Servers haben Sie eine "unspezifizierte" DateTime
übergeben. Mit anderen Worten, nur Jahr, Monat, usw., ohne irgendeinen Kontext. Wenn Sie sich die Eigenschaft .Kind
ansehen, werden Sie sehen, dass es tatsächlich DateTimeKind.Unspecified
ist.
Wenn Sie .ToUniversalTime()
für eine nicht angegebene Art von DateTime
aufrufen, übernimmt .NET den Kontext der lokalen Zeitzone des Computers, auf dem der Code ausgeführt wird. Sie können mehr über diese in der Dokumentation hier lesen. Da Ihr Server auf UTC eingestellt ist, führen alle drei Arten unabhängig von der Art der Eingabe zum selben Ergebnis. Grundsätzlich ist es ein No-Op.
Sie haben jetzt gesagt, dass Sie die Uhrzeit für die Zeitzone des Benutzers angeben möchten. Leider sind das Informationen, die der Server nicht hat. Es gibt keinen magischen HTTP-Header, der Zeitzonendetails enthält.
Es gibt jedoch Möglichkeiten, diesen Effekt zu erzielen, und Sie haben einige Optionen.
JavaScript-Methode
Dies ist wahrscheinlich die einfachste Option, erfordert aber JavaScript.
Date
-Klasse.
moment
aus der moment.js -Bibliothek verwenden. Date
oder moment
und gib es an deinen Server weiter.
2013-09-17T08:00:00.000Z
Z
am Ende. Das bedeutet, dass die Zeit in UTC ist. Date
oder ein moment
mit JavaScript geladen und dann das lokale Datum und die Uhrzeit ausgegeben. .NET-Methode, die Windows-Zeitzonen verwendet
Wenn Sie JavaScript nicht aufrufen, müssen Sie den Benutzer nach seiner Zeitzone fragen. Dies kann in einer größeren Anwendung, z. B. auf der Profilseite des Benutzers, gut funktionieren.
TimeZoneInfo.GetSystemTimeZones
, um eine Dropdown-Liste zu erstellen.
TimeZoneInfo
-Element in der Liste .Id
für den Wert und% .DisplayName
für den Text. Dann können Sie diesen Wert verwenden, wenn Sie die Zeit konvertieren möchten.
%Vor%Dies funktioniert mit Windows-Zeitzonen, die eine Microsoft-Erstellung sind, und einige Nachteile haben. Im Zeitzonen-Tag-Wiki können Sie über einige ihrer Mängel nachlesen.
.NET-Methode, die IANA-Zeitzonen verwendet
Wenn Sie die Standard-IANA-Zeitzonen wie America/New_York
oder Europe/London
verwenden möchten, können Sie eine Bibliothek wie Noda Time
Unabhängig davon, welche dieser drei Ansätze Sie wählen, müssen Sie mit den Problemen umgehen, die durch die Sommerzeit entstehen. Jedes dieser Beispiele zeigt einen "nachsichtigen" Ansatz, bei dem, wenn die von Ihnen angegebene lokale Zeit mehrdeutig oder ungültig ist, eine Regel befolgt wird, sodass Sie immer noch einen gültigen Zeitpunkt haben. Sie können dies direkt mit dem Noda Time-Ansatz sehen, wenn ich AtLeniently
aufgerufen habe. Aber es kommt auch bei den anderen vor - es ist nur implizit. In JavaScript können die Regeln je nach Browser variieren. Erwarten Sie daher keine konsistenten Ergebnisse.
Abhängig davon, welche Art von Daten Sie sammeln, können Sie entscheiden, dass es vollkommen akzeptabel ist, eine solche Annahme zu treffen. Aber in vielen Fällen ist es nicht angemessen anzunehmen. In diesem Fall müssen Sie Ihren Benutzer entweder warnen, dass die Eingabezeit ungültig ist, oder ihn fragen, welche der zwei nicht eindeutigen Zeiten gemeint sind.
In .Net können Sie dies mit TimeZoneInfo.IsInvalidTime
überprüfen und TimeZoneInfo.IsAmbiguousTime
.
Ein Beispiel für die Funktionsweise der Sommerzeit finden Sie hier . In dem "Spring-forward" -Übergang ist eine Zeit während des Übergangs ungültig.In dem "Fallback" -Übergang ist eine Zeit während des Übergangs mehrdeutig - das heißt, sie könnte entweder vor oder nach dem Übergang stattgefunden haben.
Tags und Links asp.net-mvc c# datetime timezone appharbor