Probleme mit JavaScriptSerializer UTC DateTime
Unser Kunde wollte die Datums- und Zeitwerte im Browser genauso anzeigen, wie sie in der Datenbank sind, und wir speichern sie als UTC in der Datenbank.
Anfangs hatten wir einige Probleme mit der Serialisierung und der Javascript-Seite. Die DateTime-Werte wurden zweimal verschoben - zunächst um die lokale Zeitzone des Computers und dann um die Zeitzone im Browser abzugleichen. Wir haben dies behoben, indem wir dem JavaScriptSerializer einen benutzerdefinierten Konverter hinzugefügt haben. Wir haben DateTime als DateTimeKind.Utc in der Serialize-Überschreibung markiert. Es war etwas schwierig, die Daten von Serialize zurückzuspeisen, aber wir fanden einen Uri-Hack, der dazu beitrug, DateTime-Werte im gleichen JavaScriptSerializer / Date (286769410010) / -Format zurückzugeben, ohne jedoch auf die lokale Zeit zu verschieben. Auf der Javascript-Seite haben wir die KendoUI JS-Bibliothek gepatcht, um die konstruierten Date () -Objekte so zu versetzen, dass sie als UTC-Objekte erscheinen.
Dann begannen wir auf der anderen Seite mit der Deserialisierung. Auch hier mussten wir unseren Code anpassen, um anstelle von JSON.stringify einen benutzerdefinierten Stringify zu verwenden, der die Daten beim Konvertieren von der lokalen Zeit in UTC wieder versetzt. Bisher schien alles gut zu sein.
Aber sieh dir diesen Test an:
public void DeserialiseDatesTest()
{
var dateExpected = new DateTime(1979, 2, 2,
2, 10, 10, 10, DateTimeKind.Utc);
// this how the Dates look like after serializing
// anothe issue, unrelated to the core problem, is that the "\" might get stripped out when dates come back from the browser
// so I have to add missing "\" or else Deserialize will break
string s = "\"\\/Date(286769410010)\\/\"";
// this get deserialized to UTC date by default
JavaScriptSerializer js = new JavaScriptSerializer();
var dateActual = js.Deserialize<DateTime>(s);
Assert.AreEqual(dateExpected, dateActual);
Assert.AreEqual(DateTimeKind.Utc, dateActual.Kind);
// but some Javascript components (like KendoUI) sometimes use JSON.stringify
// for Javascript Date() object, thus producing the following:
s = "\"1979-02-02T02:10:10Z\"";
dateActual = js.Deserialize<DateTime>(s);
// If your local computer time is not UTC, this will FAIL!
Assert.AreEqual(dateExpected, dateActual);
// and the following fails always
Assert.AreEqual(DateTimeKind.Utc, dateActual.Kind);
}
Warum deserialisiert JavaScriptSerializer?\/Date(286769410010)\/
Zeichenketten zu UTC-Zeit aber1979-02-02T02:10:10Z
zur Ortszeit?
Wir haben versucht, unserer benutzerdefinierten Methode eine Deserialize-Methode hinzuzufügenJavascriptConverter
Das Problem ist jedoch, dass Deserialize niemals aufgerufen wird, wenn unser JavascriptConverter die folgenden Typen hat:
public override IEnumerable<Type> SupportedTypes
{
get { return new List<Type>() { typeof(DateTime), typeof(DateTime?) }; }
}
Ich denke, Deserialize würde nur dann aufgerufen, wennSupportedTypes
enthielt Typen einiger komplexer Entitäten mit DateTime-Feldern.
So,JavaScriptSerializer
undJavascriptConverter
haben zwei Inkonsistenzen:
Gibt es eine einfache Möglichkeit, diese Probleme zu beheben? Wir haben ein bisschen Angst zu ersetzenJavaScriptSerializer
mit einem anderen Serializer, da möglicherweise einige der Bibliotheken von Drittanbietern, die wir verwenden, sich auf bestimmte "Funktionen / Fehler" von verlassenJavaScriptSerializer
.