DateTime持久化总结

我在学习Fishli李老师的博客时,看到一个话题,就是DateTime持久化, 还有人驳斥他的文章,弄的我迷糊了,因而花了点时间,一探究竟,顺便作一个总结javascript

直接上结论:java

* 1. DateTime是结构体
*
* 2. DateTime.Kind 指明此DateTime 是Utc(协调世界时) 仍是 Local(本地时间) , 可是DateTime里并不保存时区和时差值.
*
* 3. DateTime.Ticks 是0001年1月1日0点0分0秒为原点. 精确到 "0.1微秒". 指明计数周期 (1Tick = 0.1微秒)
*
* 4. dt1 == dt2, 判断的依据是Ticks是否相等, 而不考虑 Kind, 因此会出现两种状况: 1.不为同一时刻, 但值相等. 2.同一时刻, 但值不相等 .
*
* 5. 序列化时, 以Utc时间1970年1月1日0点0分0秒0毫秒为原点, 精确到 "1毫秒" ,json


* 早于原点时间显示负数,例如"\/Date(-112+0800)\/", 晚于原点时间显示正数,例如:"\/Date(991+0800)\/" .
*
*
* 假设 dt_loc.Kind = Local , dt_loc.Ticks = 621356256009910001
*
* 等效为: dt_loc.ToUniversalTime().Kind = Utc , dt_loc.ToUniversalTime().Ticks = 621355968009910001
*
* JavaScriptSerializer序列化过程:
* 计算生成Utc下的Ticks值=621355968009910001
* 改成以1970年1月1日0点0分0秒0毫秒为时间原点 ,获得 9910001
* 精度从0.1微秒降为1毫秒, (直接砍掉了后四位0001), 获得991
* 序列化为 "\/Date(991)\/"
* 序列化结果里只包含Utc的Ticks值, 不含Kind和时差值.
*
*
*
* DataContractJsonSerializer & Newtonsoft.Json (版本<=4.5)  序列化过程:
* 保持原Ticks值=621356256009910000
* 改成以1970年1月1日0点0分0秒0毫秒为时间原点 ,获得 9910000
* 精度从0.1微秒降为1毫秒, (直接砍掉了后四位0001), 获得991
* 经过TimeZoneInfo.Local.Id获得时差值: +0800
* 序列化为 "\/Date(991+0800)\/"
* 序列化结果里不含Kind, 但包含时差值,变相保存了时区信息、Kind信息(有+0800就是Local,没有+0800就是Utc).
* 学习

JavaScriptSerializer不能持久化的缘由有两个: 1. 不保存时差值   2.精度和DateTime的精度不一致spa

DataContractJsonSerializer和Newtonsoft.Json(版本<=4.5)不能持久化的缘由有一个: 1. .精度和DateTime的精度不一致.net

总结: 不能持久的关键缘由为:    "\/Date(991+0800)\/" ,  微软格式的精度和DateTime的精度不一致, 是否是javascript的Date的精度就到毫秒,微软顾及javascript, 懂的来讲说吧.. 
 
 
* 后来在网上查到了下面的资料
* .net自带的json序列化器,JavaScriptSerializer和DataContractJsonSerializer,都是序列化成微软的datetime json格式,e.g. "\/Date(1198908717056)\/"orm

Newtonsoft.Json的行为是这样的。ip

<=4.5,也是序列化成微软的datetime json格式,e.g. "\/Date(1198908717056+0800)\/".博客

>4.5,序列化成ISO标准时间格式,"2016-05-05T14:59:30.4617225+08:00" ,  精确到小数点7位了, 精度和DateTime一致了string

 

因而我下载了5.0.1版本的Newtonsoft. 试了下,  的确能够持久化了.

var settings = new JsonSerializerSettings();

settings.DateFormatHandling = DateFormatHandling.IsoDateFormat;   // 若是要输出ISO标准时间,能够经过dateTimeFormat进行设置。

string s0 = JsonConvert.SerializeObject(dt_loc, settings);

DateTime Newtonsoft_dt2 = JsonConvert.DeserializeObject<DateTime>(s0);

dt_loc == Newtonsoft_dt2 为 true

 

结论就是:  Newtonsoft.Json(版本>4.5) 能持久化的关键缘由就是, 序列化时采起ISO标准, 保存了时差, 保持了精度,因此反序列化时才能原本来本的还原.

那篇反驳的文章则验证持久化的方法不对,  他将序列化后的JSON字符结果放到javascript中可以解析出时间,  就认为持久化没有问题,  

可是他没有注意, JSON字符里的Ticks 和 DateTime里的Ticks 精度并不同, JSON字符里的Ticks的精度只到1毫秒,  而 DateTime里的Ticks的精确到0.1微秒,

验证持久化最简单的办法就是, 判断一下Kind是否一致, 再验证一下Ticks是否一致 , 最后就是 dt1 == dt2 是否返回true啊,

他这三个一个没验证, 居然就说持久化没问题,太不严谨了,仍是严谨点好, 否则理解老是有误差, 误导了别人就很差了.

相关文章
相关标签/搜索