JavaScriptSerializer UTC DateTime issues
我们的客户希望在浏览器中显示日期和时间值,就像它们在数据库中一样,我们将它们作为UTC存储在数据库中。
起初我们在序列化和Javascript方面遇到了一些问题。 DateTime值被移动了两次 - 首先匹配机器的本地时区,然后匹配浏览器中的时区。我们通过向JavaScriptSerializer添加自定义转换器来修复它。我们在Serialize覆盖中将DateTime标记为DateTimeKind.Utc。从Serialize中提取数据有点困难,但是我们发现了一些Uri hack,这有助于在相同的JavaScriptSerializer / Date(286769410010)/格式中返回DateTime值,但没有转移到本地时间。在Javascript方面,我们修补了KendoUI JS库来偏移构造的Date()对象,使它们看起来好像是UTC。
然后我们开始在另一方面工作,反序列化。同样,我们必须调整我们的代码以使用自定义stringify而不是JSON.stringify,这会在从本地时间转换为UTC时再次抵消数据。到目前为止,一切似乎都很好。
但看看这个测试:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | 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); } |
为什么JavaScriptSerializer将
我们尝试将Deserialize方法添加到自定义
1 2 3 4 | public override IEnumerable<Type> SupportedTypes { get { return new List<Type>() { typeof(DateTime), typeof(DateTime?) }; } } |
我想,只有当
所以,
- Serialize考虑了每个数据项的SupportedTypes中的简单类型,但Deserialize忽略了简单类型
- 反序列化将某些日期反序列化为UTC和一些 - 作为本地时间。
有没有简单的方法来解决这些问题?
我们有点害怕将
在JavaScript中,如果您可以保证您将在较新的浏览器上运行,那么请使用:
1 | date.toISOString() |
参考这里。
如果您想要完整的跨浏览器和旧浏览器支持,请改用moment.js。
UPDATE
顺便说一句,如果你真的想继续使用
1 2 3 4 | // note, you were missing the milliseconds in your example, I added them here. s =""1979-02-02T02:10:10.010Z""; dateActual = js.Deserialize<DateTimeOffset>(s).UtcDateTime; |
您的测试现在将通过。