JavaScriptSerializer UTC DateTime问题

我们的客户想要在浏览器中显示date和时间值,就像它们在数据库中一样,我们将它们作为UTC存储在数据库中。

起初我们在序列化和Javascript方面有一些问题。 DateTime值被移位两次 – 首先匹配机器的本地时区,然后匹配浏览器中的时区。 我们通过向JavaScriptSerializer添加自定义Converter来修复它。 我们将DateTime标记为Serialize覆盖中的DateTimeKind.Utc。 从Serialize中反馈数据有点困难,但是我们发现了一些Uri破解,这有助于在相同的JavaScriptSerializer / Date(286769410010)/格式中返回DateTime值,但不会转移到本地时间。 在Javascript方面,我们修补了KendoUI JS库来抵消构造的Date()对象,使它们看起来好像是UTC一样。

然后我们开始在另一边工作,反序列化。 再一次,我们不得不调整我们的代码来使用自定义string,而不是JSON.stringify,当从本地时间转换为UTC时再次偏移数据。 一切似乎都很好。

但看看这个testing:

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反序列化\/Date(286769410010)\/string到UTC时间,但1979-02-02T02:10:10Z到当地时间?

我们尝试添加一个Deserialize方法到我们的自定义JavascriptConverter但问题是如果我们的JavascriptConverter具有以下types,那么Deserialize永远不会被调用:

  public override IEnumerable<Type> SupportedTypes { get { return new List<Type>() { typeof(DateTime), typeof(DateTime?) }; } } 

我猜,Deserialize只有在SupportedTypes包含一些具有DateTime字段的复杂实体的types时才会被调用。

所以, JavaScriptSerializerJavascriptConverter有两个不一致的地方:

  • Serialize考虑了每个数据项的SupportedTypes中的简单types,但反序列化忽略了简单types的types
  • 反序列化将一些date反序列化为UTC,还有一些date为当地时间。

有没有简单的方法来解决这些问题? 我们有点害怕用其他序列化程序代替JavaScriptSerializer ,因为我们正在使用的一些第三方库依赖于JavaScriptSerializer某些“function/错误”。

JavaScriptSerializerDataContractJsonSerializer充满了bug。 使用json.net来代替。 即使微软已经在ASP.Net MVC4和其他最近的项目中做了这个切换。

/Date(286769410010)/格式是专有的,由Microsoft组成。 它有问题,并没有得到广泛的支持。 你应该到处使用1979-02-02T02:10:10Z格式。 这在ISO8601和RF3339中定义。 它既机器和人类可读,词汇sorting,文化不变和明确。

在JavaScript中,如果您可以保证您将在较新的浏览器上运行,请使用:

 date.toISOString() 

在这里引用 。

如果您想要完整的跨浏览器和较老的浏览器支持,请改用moment.js 。

UPDATE

顺便说一句,如果你真的想继续使用JavaScriptSerializer ,你可以反序列化到一个DateTimeOffset ,这将保留正确的时间。 您可以从那里获得UTC DateTime时间,如下所示:

 // 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; 

你的testing现在会通过。