私たちのクライアントは、日付と時刻の値をデータベースとまったく同じようにブラウザーに表示したいと考えており、それらを UTC としてデータベースに保存しています。
最初は、シリアライゼーションと Javascript 側でいくつかの問題がありました。DateTime 値が 2 回シフトされました。最初はマシンのローカル タイム ゾーンに一致し、次にブラウザのタイム ゾーンに一致します。カスタム コンバーターを JavaScriptSerializer に追加することで、この問題を修正しました。Serialize オーバーライドで DateTime を DateTimeKind.Utc としてマークしました。Serialize からデータをフィードバックするのは少し大変でしたが、同じ JavaScriptSerializer /Date(286769410010)/ 形式で DateTime 値を返すのに役立つ Uri ハックが見つかりましたが、現地時間にシフトすることはありませんでした。Javascript 側では、KendoUI JS ライブラリにパッチを適用して、構築された Date() オブジェクトをオフセットし、それらが UTC であるかのように表示されるようにしました。
次に、反対側のデシリアライゼーションに取り組み始めました。ここでも、JSON.stringify の代わりにカスタム stringify を使用するようにコードを調整する必要がありました。これは、現地時間から UTC に変換するときにデータをオフセットします。これまでのところ、すべてが順調に見えました。
しかし、このテストを見てください:
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);
}
\/Date(286769410010)\/
JavaScriptSerializerが文字列を UTC 時間ではなく1979-02-02T02:10:10Z
ローカル時間にデシリアライズするのはなぜですか?
カスタムに Deserialize メソッドを追加しようとしましたJavascriptConverter
が、問題は、JavascriptConverter に次の型がある場合、Deserialize が呼び出されないことです。
public override IEnumerable<Type> SupportedTypes
{
get { return new List<Type>() { typeof(DateTime), typeof(DateTime?) }; }
}
SupportedTypes
Deserialize は、 DateTime フィールドを持ついくつかの複雑なエンティティの型が含まれている場合にのみ呼び出されると思います。
したがって、2 つの矛盾がありますJavaScriptSerializer
。JavascriptConverter
- Serialize では、すべてのデータ項目について、SupportedTypes の単純型が考慮されますが、Deserialize は、単純型についてはそれを無視します
- Deserialize は、一部の日付を UTC として、一部を現地時間として逆シリアル化します。
これらの問題を解決する簡単な方法はありますか? 私たちがJavaScriptSerializer
使用しているサードパーティのライブラリの一部は、JavaScriptSerializer
.