木子屋 Dnawo's BLOG

JavascriptSerializer序列化/反序列化DateTime少了8小时原因分析

👤 dnawo 📅 2015-01-23 👁 5540 👍 0 💬 0 🔄 本站原创
先看一个栗子:

JavascriptSerializer serializer = new JavascriptSerializer();
DateTime now = DateTime.Parse("2015-01-23 00:00:00");
Console.WriteLine(serializer.Deserialize<DateTime>(serializer.Serialize(now)));

图片

如上图所示,反序列化后的时间比原先少了8个小时,是什么原因造成的?用ILSpy对JavascriptSerializer反编译,得到源码如下:

JavascriptSerializer.Serialize -> JavascriptSerializer.SerializeDateTime:
private static void SerializeDateTime(DateTime datetime, StringBuilder sb, JavascriptSerializer.SerializationFormat serializationFormat)
{
	if (serializationFormat == JavascriptSerializer.SerializationFormat.JSON)
	{
		sb.Append("\"\\/Date(");
		sb.Append((datetime.ToUniversalTime().Ticks - JavascriptSerializer.DatetimeMinTimeTicks) / 10000L);
		sb.Append(")\\/\"");
		return;
	}
	sb.Append("new Date(");
	sb.Append((datetime.ToUniversalTime().Ticks - JavascriptSerializer.DatetimeMinTimeTicks) / 10000L);
	sb.Append(")");
}

JavascriptSerializer.Deserialize -> JavascriptObjectDeserializer.DeserializeStringIntoDateTime:
private object DeserializeStringIntoDateTime()
{
	Match match = Regex.Match(this._s.ToString(), "^\"\\\\/Date\\((?<ticks>-?[0-9]+)(?:[a-zA-Z]|(?:\\+|-)[0-9]{4})?\\)\\\\/\"");
	string value = match.Groups["ticks"].Value;
	long num;
	if (long.TryParse(value, out num))
	{
		this._s.MoveNext(match.Length);
		DateTime dateTime = new DateTime(num * 10000L + JavascriptSerializer.DatetimeMinTimeTicks, DateTimeKind.Utc);
		return dateTime;
	}
	return this.DeserializeString();
}

JavascriptSerializer序列化时把时间转成了UTC时间,而反序列化时没转回本地时间,本地时间和UTC时间相差为8小时,这就导致了上边的问题,因此,反序列化后我们需调用ToLocalTime方法将DateTime转成本地时间:

JavascriptSerializer serializer = new JavascriptSerializer();
DateTime now = DateTime.Parse("2015-01-23 00:00:00");
Console.WriteLine(serializer.Deserialize<DateTime>(serializer.Serialize(now))[color=Red].ToLocalTime()[/color]);

图片

另一个解决方法是改用DataContractJsonSerializer类进行序列化/反序列化,这个类没有上边的问题。

评论(0)

暂无评论。

计算题
评论需审核通过后显示
← 上一篇 C# DateTime去掉时分秒几种方法 下一篇 → DataGridView控件必须绑定到IBindingList对…