你需要掌握的有关.NET DateTime类型的知识点和坑位 都在这里
引言
DateTime数据类型是一个复杂的问题,复杂到足以让你在编写【将日期从Web服务器返回到浏览器】简单代码时感到困惑。
ASP.NET MVC 5和 Web API 2/ASP.NETCore 以不同方式序列化日期,这可能会给在一个Web应用程序中同时使用这两个序列化的开发人员带来更多混淆。
本文会尽量覆盖 ASP.NET / ASP.NETCore 中与 Date/Time有关的歧义、参数绑定、序列化相关的知识点和坑位。
Date/Time值歧义和应对策略
使用Datetime最大的问题在于歧义,整个地球分为24个时区,每个时区都有自己的本地时间
例如一个DateTime值指示了本地时间,这个值在同时区的其他系统依然标示了同一时间点; 但是在其他时区以外,这个DateTime值就会有各自的解释。
电邮中若有Sun , 04, June 2019 9:45:29 +0800说明信件发送第时间是2019年6月04日,星期日,上午9点45分29秒,该地区领先UTC8小时 (+800,就是东八区时间)。对于发这封邮件的时间,北京本地时9点45,伦敦是凌晨1点45 ......
正因为这个现状,在Internet以及无线电通信时,时间的统一很重要。
业界提出了不同的格式来明确地表示单一时间点, Web开发行业提出了不同的解决方案以明确定义时间值。
UTC时间
在国际无线电通信中,为避免各自为战而普遍使用一个标准时间,称为协调世界时(UTC)
UTC是0时区的时间值,与格林威治标准时间(GMT)一样,都与英国伦敦的当地时间相同
UTC能准确代表单一时间点,UTC 时间对于住在加利福尼亚和中国的人来说都是一样的。
如果把以上北京时间2019/06/04 09:45:29转化为UTC时间,可以使用以下公式: UTC + 时区差 = 当地时间。
因为北京时间是东8区,所以这个点UTC时间是 2019/06/04 02:45:29(也可认为该值是伦敦时间)
开发者可以考虑的解决方案 是: 使用UTC时间存储date/time、服务端维护、计算也使用UT时间、将UTC时间发送到浏览器,浏览器javascript在Web页上转化为当地时间。
ISO 8601
Web上有许多时间显示格式,但最著名并大规模采用的是ISO-8601 标准。https://www.cl.cam.ac.uk/~mgk25/iso-time.html
当没有更多信息的时候,只包含Date/Time 的写法被假定为当地时间,要指示该时间是UTC时间,可在Datetime值后面加上字母 z,
在Datetime值后面增加 +hh:mm、 +hhmm, -hh 可指示该时间值相对于UTC时间的偏移
// Date: 2016-10-12 10:18:42 UTC time ISO 8601: 2016-10-11T10:18:42z == 2016-10-11T10:18:42+00:00// Date: 2016-10-12 10:18:42 Pacific time, 表示该时间值相对于UTC时间值提前6小时 ISO 8601: 2016-10-11T10:18:42-06:00
.Net中关于Date/Time的实现
.Net 4.0+ 提供的各种结构已经全方位支持 date, timezone, timezone之间的转化,足以解决开发者遇到的Date/Time相关的问题。
DateTime
DateTime 定义了一个特殊的date/time, 内置的Kind属性提供了受限的时区信息:
① DateTimeKind.UTC 指定了UTC的DateTime,明确定义了单一时间点
② DateTimeKind.Local 指示了本地时间,这个值在具有相同时区的其他系统依然能够定义一个时间点,但是在其他时区以外,这个DateTime值会有不同解释。
③ DateTimeKind.Unspecified 更没有兼容性,仅表示时间值
我们关注 DateTime.ToUniversalTime() 方法的表现,当DateTime被设定为Unspecified时候, ToUniversalTime会首先假定该值是 Local
// 以下代码的执行环境是北京时间 var dt1 = new DateTime(2019, 6, 4, 9, 45, 29, DateTimeKind.Local); var dt1_temp = dt1.ToUniversalTime();var dt2 = new DateTime(2019, 6, 4, 9, 45, 29, DateTimeKind.Utc); var dt2_temp = dt2.ToUniversalTime();var dt3 = new DateTime(2019, 6, 4, 9, 45, 29, DateTimeKind.Unspecified); var dt3_temp = dt3.ToUniversalTime(); var dt4 = new DateTime(2019, 6, 4, 9, 45, 29); // Unspecified DateTime var dt4_temp = dt4.ToUniversalTime();
Console.WriteLine(dt1_temp.ToString());Console.WriteLine(dt2_temp.ToString()); Console.WriteLine(dt3_temp.ToString()); // Unspecified DateTime在被应用ToUniversalTime 方法时会被假定是LocalConsole.WriteLine(dt4_temp.ToString());
output: 2019/6/4 1:45:292019/6/4 9:45:29 2019/6/4 1:45:292019/6/4 1:45:29
when to use datetime?
你只处理当地时间,你没有跨越时区的计算
你只处理 UTC时间
处理抽象日期/时间(使用 Unspecified):例如跨国公司的跨时区门店都在早上9点开业
DateTimeOffset
表示时间点,通常表示为一天中相对于UTC时间的日期/时间,该结构体自然带有相对于UTC时间的偏移信息
when to use DateTimeOffset?
代码需要应对不同时区的时间值
时区之间相互转化
需要进行跨时区的计算
Date/Time 序列化
Web API2 和ASP.NET Core内置的JSON序列化器是Newtonsoft.Json,JSON.NET将日期时间序列化为ISO-8601格式:
Date value
|
serialized value
|
DateTime.Now (Pacific time)
|
2016-10-11T19:25:34.8346658-07:00
|
DateTime.UtcNow
|
2016-10-12T01:25:34.8346658Z
|
new DateTime(2016, 6, 6, 4, 5,5 )
|
2016-06-06T04:05:05
|
new DateTimeOffset(new DateTime(2016, 6, 6, 4, 5,5 ), new TimeSpan(-2, 0,0))
|
2016-06-06T04:05:05-02:00
|
这样的格式在客户端需要使用JavaScript做一些本地转化, 转化后的值无法体现时区。
public ActionResult Contact() {var data = new Test{Name = "hj",Time = DateTime.Now};return Json(data,JsonRequestBehavior.AllowGet);} output:{
JavaScriptSerializer还有更多缺点,现在社区鼓励使用Json.Net 序列化器。
Date/Time字符串转换
在开发中,常涉及Date/Time 参数绑定和字符串转换, 当中也有一些坑位需要规避。
一个时间日期字符串, 若没有相对于UTC的偏移信息,转换后的DateTime对象的DateTimKind是Unspecified;
若指定了offset,转换后的DateTime对象的DateTimeKind是Local, 并且时间值被调整到机器的当地时间。
最近我们生产环境WebSite再迁移到k8s集群 (UTC时间)之后,就遇到这样的问题:
订单转储的预期是:北京时间2019-05-11--->2019-05-12
实际情况是在网站端转换为Unspecified, 而进一步ToUniversalTime()过滤的时候,该时间段又被假定是机器的当地时间, 也就是说查询时间段变成了: 伦敦时间2019-05-11--->2019-05-12
这样自然与预期不符。
解决思路: 添加偏移信息,告知明确的时间段: 2019-05-11 00:00:00+08:00 ----> 2019-05-12 00:00:00+08:00
感谢您的认真阅读,如有问题请大胆斧正;觉得有用,请下方或加关注。
本文欢迎转载,但请保留此段声明,且在文章页面明显位置注明本文的作者及原文链接。
转载于:https://www.cnblogs.com/JulianHuang/p/10967289.html
你需要掌握的有关.NET DateTime类型的知识点和坑位 都在这里相关推荐
- datetime类型需要指定长度吗_你真的用对数据库了吗?
作者:浮雷原文:https://juejin.im/post/6871969929365553165 背景 因为工作岗位的原因,负责制定了关于后端组数据库的规约规范,作为所有产品线的规范,历经几版的修 ...
- mysql java datetime_Java向mysql数据库插入datetime类型数据实例(精)
在Mysql数据库中日期跟时间有两种: 1.date类型,date类型也就是我们常见的储存yyyy-MM-dd类型的日期,它不能储存时间,也就是只能储存日期, 2.dateitme就是可以储存日期同时 ...
- 解决Python自带的json序列化工具不能序列化datetime类型数据问题
解决Python自带的json序列化工具不能序列化datetime类型数据问题 参考文章: (1)解决Python自带的json序列化工具不能序列化datetime类型数据问题 (2)https:// ...
- 解决Asp.net Mvc返回JsonResult中DateTime类型数据格式的问题
问题背景: 在使用asp.net mvc 结合jquery esayui做一个系统,但是在使用使用this.json方法直接返回一个json对象,在列表中显示时发现datetime类型的数据在转为字符 ...
- C# WebAPI中DateTime类型字段在使用微软自带的方法转json格式后默认含T的解决办法...
C# WebAPI中DateTime类型字段在使用微软自带的方法转json格式后默认含T的解决办法 原文:C# WebAPI中DateTime类型字段在使用微软自带的方法转json格式后默认含T的解决 ...
- sql server 中将datetime类型转换为date,或者time
sql server 中将datetime类型转换为date,或者time 2008年01月14日 星期一 14:46 这个转换总是记不住,用到的时候就找,现贴上来,以备查用. datetime类型转 ...
- python mysql写入速度加快_解决python写入mysql中datetime类型遇到的问题
解决python写入mysql中datetime类型遇到的问题 发布时间:2020-08-31 16:46:47 来源:脚本之家 阅读:89 作者:WilliamDescant 刚开始使用python ...
- 解决Entity Framework中DateTime类型字段异常
从 datetime2 数据类型到 datetime 数据类型的转换产生一个超出范围的值 具体的错误原因是:C#中的DateTime类型比SqlServer中的datetime范围大.SqlServe ...
- 转:SqlServer中的datetime类型的空值和c#中的DateTime的空值的研究
SqlServer中的datetime类型的空值和c#中的DateTime的空值的研究 在SqlServer 2000中datetime 的空值即默认值为1900-01-01 00:00 :00,C# ...
最新文章
- css txt-aline,CSS规则定义.doc
- 嵌入式多媒体设计7--QDockWidget大小调整及隐藏标题
- 如何将Twitter的内容导入到SAP CRM和C4C
- jQuery 插件-(初体验一)
- 抢鲜体验:openGauss 安装编译过程要点及问题解决
- Mysql的master,slave的配置
- ajax post常用请求头
- eclipse下的mybatis插件:MyBatipse
- java生成pdf的流_Java 文件输出流.pdf
- Java Graphics2D 在图片上画(微信昵称)含有特殊符号(Emoji)的文字
- kafka下载与安装教程
- 二进制码和格雷码转换问题
- 硬改TP-WR886N v5 路由器刷入源码编译的openWRT/LEDE系统
- python数据可视化学习之随机漫步
- 大学一年级计算机应用课程,计算机应用*的课程教学计划
- ORA-01017: invalid username/password; logon denied ORA-02063: 紧接着line(源于DBLINKN~~~)
- 零钱兑换问题c语言编程,leetcode- 零钱兑换 II(背包问题-总结-复盘)
- 防沉迷系统?游戏运营商笑了!
- EMD经验模态分解实例(转C代码)
- 34. 实战:基于某api实现歌曲检索与下载(附完整源代码)