DateTime持久化总结

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

直接上结论:

* 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毫秒" ,

* 早于原点时间显示负数,例如"\/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的精度不一致

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

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

Newtonsoft.Json的行为是这样的。

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

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

于是我下载了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啊,

他这三个一个没验证, 竟然就说持久化没问题,太不严谨了,还是严谨点好, 不然理解总是有偏差, 误导了别人就不好了.

(0)

相关推荐

  • asp.net core 3.0 MVC JSON 全局配置

    asp.net core 3.0 MVC JSON 全局配置 System.Text.Json(default) startup配置代码如下: using System.Text.Encodings. ...

  • 关于.NetCore与.Netframework 对于DataSet的序列化与反序列化问题的探讨.

    最近完善自己的项目中,将很多原先的framework下的类库都转为.net standard类库,服务自然也往.netCore上转.因此,写了一个WebApi做为服务来完善自己的类库程序. 在我的程序 ...

  • VB.NET 把引用的DLL打包到exe里面,制作绿色软件

    VB.NET 把引用的DLL打包到exe里面,制作绿色软件   今天以大家常用DLL'Newtonsoft.Json'为例给大家做个示范; 1.第一步新建项目 2.第二步,新建项目后,在窗体添加一个按 ...

  • DateTime.TryParse和Z字母的大小写

    最近,我受命以从后端到前端的特定格式提供日期,我注意到我发现自己的行为有些奇怪. private static void OutputDateInfo(string value){ Console.W ...

  • python测试开发django-79.ORM查询之datetime()格式化(extra )

    前言 django 查询数据库的时候,数据存的是 datetime() 日期格式的数据 '2020-06-22 22:34:14' 但是我们用 ORM 查询的时候,查询出来的结果是 'datetime ...

  • 字符串转DateTime

    将文本正确转换为 DateTime 需要执行三个子任务:1.正确格式的日期和时间字符串.2.区域性,不同地区的日期和时间表示格式有区别,字符串格式有区别.3.指定转换格式,例如转换后的DateTime ...

  • PHP中的数据库连接持久化

    PHP中的数据库连接持久化 数据库的优化是我们做web开发的重中之重,甚至很多情况下其实我们是在面向数据库编程.当然,用户的一切操作.行为都是以数据的形式保存下来的.在这其中,数据库的连接创建过程有没 ...

  • [PHP小课堂]PHP中的数据库连接持久化

    [PHP小课堂]PHP中的数据库连接持久化 关注公众号:[硬核项目经理]获取最新文章 添加微信/QQ好友:[xiaoyuezigonggong/149844827]免费得PHP.项目管理学习资料 知乎 ...

  • Sentinel Dashboard(基于1.8.1)流控规则持久化到Nacos——涉及部分Sentinel Dashboard源码改造

    前言 之前虽然也一直在使用sentinel实现限流熔断功能,但却没有好好整理之前看的源码与资料,今天有时间将之前自己整理过的资料写成一篇博文,或者是是一篇关于Sentinel(基于目前最近版本1.8, ...

  • 第25天:Python datetime 和 time

    在前面的章节中已经介绍了一些 Python 常用的模块,本节再介绍两个模块 datetime 模块和 time 模块,这两个模块主要用于转换日期格式的功能. datetime模块 datetime 模 ...

  • 第46天:Flask数据持久化

    Web 应用离不开数据存储,今天就来学习下 Flask 中如何与数据库交互,最后我们将做一个提交的实例 Flask 中最方便用的数据库框架是 flask_sqlalchamy,是对 SQLAlcham ...

  • Docker 数据持久化Volume

    Docker镜像是基于联合文件系统(Union File System)的一种层式结构,由一系列指令一步一步构建出来.Docker镜像被存储在一系列的只读层中.当我们创建一个容器时,Docker会读取 ...