JavaScriptSerializer正在从日期中减去一天。

20
我将使用JavaScriptSerializer对DateTime进行序列化,但是当我反序列化时,会显示比序列化日期少一天:
以下是测试内容:
  DateTime startDate=new DateTime(2012,1,20);//set the 20th of January
  JavaScriptSerializer  serializer=new JavaScriptSerializer();
  string serializeDate= serializer.Serialize(startDate);
  DateTime afterDeserialize= serializer.Deserialize<DateTime>(serializeDate);//I get 19th of Jan
  Assert.Equals(startDate, afterDeserialize);

首先,我认为这是由于JavaScript日期时间格式引起的,但我知道对于JavaScript来说,月份是零索引0=一月,但我得到的日期比原始日期少一天。

解决方案1:搞时间区等操作。解决方案2:将年、月和日作为单独的值存储,然后在反序列化后重新组合。 - JDB
3个回答

20

这不是随意损失一天,而是转换为UTC日期(或者我应该说使用UTC日期格式中的日期),这样当它解序列化时,您将不再处于个人时区内。基本上它执行的是:

DateTime whateverDate = /* incoming date */;
long ticks = whateverDate.ToUniversalTime() // make UTC
  .Subtract(new DateTime(1970, 1, 1))       // subtract UNIX Epoch
  .TotalMilliseconds();                     // get milliseconds since then
// push in to the "\/Date(ticks)\/" format
String value = String.Format(@"\/Date({0})\/", ticks);

然而,请尝试以下操作:

// or you rely on it serializing, then bring it back to your own local time
// (apply the time zone).
afterDeserialize = afterDeserialize.ToLocalTime();

现在,您将把UTC时间转换为本地时间(应用时区)。
通过您的测试:
DateTime startDate              = new DateTime(2012,1,20);
JavaScriptSerializer serializer = new JavaScriptSerializer();
String serializeDate            = serializer.Serialize(startDate);
DateTime afterDeserialize       = serializer.Deserialize<DateTime>(serializeDate)
                                  .ToLocalTime(); // Note: this is added

Assert.Equals(startDate, afterDeserialize); // pass!

2
这是已记录的行为,尽管非常不清楚。 - JDB
DateTime startDate = new DateTime(2012, 1, 20).ToUniversalTime(); 这行代码将startDate设置为1月19日?而且在反序列化时也会得到同样的结果…为什么会这样呢? - Zaheer Ahmed
1
这是一篇博客,详细解释了问题:http://blog.devarchive.net/2008/02/serializing-datetime-values-using.html - Evelie
@ZaheerAhmed - 这是在更改时区。您的日期附带了隐式的午夜,因此在时区转换中可能会丢失几个小时,导致日期发生更改。 - JDB
@ZaheerAhmed - иҖғиҷ‘дҪҝз”ЁDateTimeOffset并д»ҘISO8601ж јејҸеәҸеҲ—еҢ–пјҢдҪҝз”ЁJson.Netд»ЈжӣҝJavaScriptSerializerгҖӮ - Matt Johnson-Pint
显示剩余2条评论

5

我曾经遇到同样的问题,并通过使用以下方法解决了它:

Newtonsoft.Json.JsonConvert.SerializeObject()

取代

new System.Web.Script.Serialization.JavaScriptSerializer().Serialize().

后一个调用将把您的DateTime转换为某个随机时区(GMT+0似乎是硬编码)。

2

在反序列化JavaScriptSerializer时,输出结果是UTC (世界标准时间),由于小时数的变化会导致日期发生变化。正如Brad Christie所建议的,将DateTime更改为UTC可以解决这个问题。

但实际上没有必要更改:

DateTime startDate = new DateTime(2012, 1, 20).ToUniversalTime();

由于已经将其视为世界标准时间,因此我只需将反序列化的输出转换为 LocalTime

 DateTime afterDeserialize= serializer.Deserialize<DateTime>(serializeDate);
 afterDeserialize.ToLocalTime();

它解决了这个问题。


有趣,我正在输入这个更新到我的答案中。;-) - Brad Christie
),我会标记您的答案为正确,并将其放在这里,以帮助其他人。 - Zaheer Ahmed

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接