DateTime和DateTimeOffset是同胞兄弟吗?
小编在日常开发中,用得最多的时间类型就是DateTime,直到一次偶然的邂逅,让小编遇见了DateTimeOffset。当时小编也是一脸迷茫,因为在小编的C#编程字典里就没出现过DateTimeOffset的字样,实属惭愧。于是心中立马产生疑惑:DateTimeOffset是用来干嘛的?它和DateTime之间又是什么关系?带着种种疑问和不解,小编今天就带你一起一窥究竟!
开场前,先了解下GMT、UTC、TimeZone这三个时间概念
GMT:Greenwich Mean Time,格林威治平时(也称格林威治时间)。它规定太阳每天经过位于英国伦敦郊区的皇家格林威治天文台的时间为中午12点。1972年之前,格林威治时间(GMT)一直是世界时间的标准。1972年之后,GMT 不再是一个时间标准了,取而代之的是UTC。
UTC:Coodinated Universal Time,协调世界时,又称世界统一时间、世界标准时间、国际协调时间。UTC 是现在全球通用的时间标准,全球各地都同意将各自的时间进行同步协调。
TimeZone: 时间区域,简称时区。按照规定从格林威治本初子午线起,经度每向东或者向西间隔15°,就划分一个时区,在这个区域内,大家使用同样的标准时间。全球共分为24个标准时区,相邻时区的时间相差一个小时。
举个例子:北京位于东八区,和伦敦时间(UTC时间)相差+8个小时。当小编每天早上8点出门上班的时候 ,大洋彼岸的英国人民正处于睡梦中,因为那儿正值午夜零点,这就是我们常说的时差。顺带提一句,虽然我国地域辽阔横跨5个时区,但统一采用北京时间作为标准时间,目的就是为了方便时间管理。
首先登场的是:DateTime
DateTime表示的是一个日期和时间值。这里我们先思考一个问题:假设有个陌生人电话告诉你现在时间是某月某日某时某分,但你又不知道对方在哪里,那么这个时间对你来说是不清晰的,它可能是当地时间(东京时间、悉尼时间...),也有可能是UTC时间。因此DateTime有个只读属性Kind,它是一个DateTimeKind枚举,用来表示时间类型。定义如下:
1 public enum DateTimeKind
2 {
3 // 未指明是UTC时间,还是当地时间
4 Unspecified = 0,
5 // 表示UTC时间
6 Utc = 1,
7 // 表示本地时间
8 Local = 2
9 }
通过DateTime构造函数,可以看出Kind属性值是由构造函数传入的。下面来看DateTime的几种常见用法:
1 DateTime dt1 = new DateTime(2023, 7, 27, 8, 40, 25);
2 Console.WriteLine($"DateTime:{dt1}, 时间类型:{dt1.Kind}, 转本地时间:{dt1.ToLocalTime()},转UTC时间:{dt1.ToUniversalTime()}");
3
4 DateTime dt2 = DateTime.Now;
5 Console.WriteLine($"DateTime:{dt2}, 时间类型:{dt2.Kind}, 转本地时间:{dt2.ToLocalTime()},转UTC时间:{dt2.ToUniversalTime()}");
6
7 DateTime dt3 = DateTime.UtcNow;
8 Console.WriteLine($"DateTime:{dt3}, 时间类型:{dt3.Kind}, 转本地时间:{dt3.ToLocalTime()},转UTC时间:{dt3.ToUniversalTime()}");
9
10 DateTime dt4 = new DateTime(2023, 7, 27, 8, 40, 25, DateTimeKind.Local);
11 Console.WriteLine($"DateTime:{dt4}, 时间类型:{dt4.Kind}, 转本地时间:{dt4.ToLocalTime()},转UTC时间:{dt4.ToUniversalTime()}");
12
13 DateTime dt5 = new DateTime(2023, 7, 27, 8, 40, 25, DateTimeKind.Utc);
14 Console.WriteLine($"DateTime:{dt5}, 时间类型:{dt5.Kind}, 转本地时间:{dt5.ToLocalTime()},转UTC时间:{dt5.ToUniversalTime()}");
输出结果:
DateTime: 2023 / 7 / 27 8:40:25, 时间类型: Unspecified, 转本地时间: 2023 / 7 / 27 16:40:25,转UTC时间: 2023 / 7 / 27 0:40:25
DateTime: 2023 / 7 / 27 14:04:00, 时间类型: Local, 转本地时间: 2023 / 7 / 27 14:04:00,转UTC时间: 2023 / 7 / 27 6:04:00
DateTime: 2023 / 7 / 27 6:04:00, 时间类型: Utc, 转本地时间: 2023 / 7 / 27 14:04:00,转UTC时间: 2023 / 7 / 27 6:04:00
DateTime: 2023 / 7 / 27 8:40:25, 时间类型: Local, 转本地时间: 2023 / 7 / 27 8:40:25,转UTC时间: 2023 / 7 / 27 0:40:25
DateTime: 2023 / 7 / 27 8:40:25, 时间类型: Utc, 转本地时间: 2023 / 7 / 27 16:40:25,转UTC时间: 2023 / 7 / 27 8:40:25
由此可见,DateTime是通过Kind属性来区分是本地时间还是UTC时间,同时本地时间和UTC时间之间可以相互转换,转换条件就是根据你电脑当前所设置的时区。不足之处就是DateTime提供了非常有限的时区信息,如果不看Kind属性,你无法判断它是来自本地时间还是UTC时间,因此在跨时区系统间的数据移植性较差(除非是指定是UTC时间)。
接着出场的就是:DateTimeOffset
DateTimeOffset表示一个时间点,通常以相对于协调世界时 (UTC) 的日期和时间来表示。它既包含了DateTime属性,又包含了一个TimeSpan类型的Offset属性(表示相对于UTC时间的偏移量).
通过DateTimeOffset构造函数,可以看出Offset属性值是由构造函数传入的。下面来看DateTimeOffset的几种常见用法:
1 DateTimeOffset dto1 = new DateTimeOffset(2023, 7, 27, 8, 40, 25, TimeSpan.Zero);
2 Console.WriteLine($"DateTimeOffset:{dto1}, 时间偏移:{dto1.Offset}, 转本地时间:{dto1.ToLocalTime()},转UTC时间:{dto1.ToUniversalTime()}");
3
4 DateTimeOffset dto2 = DateTimeOffset.Now;
5 Console.WriteLine($"DateTimeOffset:{dto2}, 时间偏移:{dto2.Offset}, 转本地时间:{dto2.ToLocalTime()},转UTC时间:{dto2.ToUniversalTime()}");
6
7 DateTimeOffset dto3 = DateTimeOffset.UtcNow;
8 Console.WriteLine($"DateTimeOffset:{dto3}, 时间偏移:{dto3.Offset}, 转本地时间:{dto3.ToLocalTime()},转UTC时间:{dto3.ToUniversalTime()}");
9
10 DateTimeOffset dto4 = new DateTimeOffset(2023, 7, 27, 8, 40, 25, new TimeSpan(8, 0, 0));
11 Console.WriteLine($"DateTimeOffset:{dto4}, 时间偏移:{dto4.Offset}, 转本地时间:{dto4.ToLocalTime()},转UTC时间:{dto4.ToUniversalTime()}");
12
13 DateTimeOffset dto5 = new DateTimeOffset(new DateTime(2023, 7, 27, 8, 40, 25), new TimeSpan(-8, 0, 0));
14 Console.WriteLine($"DateTimeOffset:{dto5}, 时间偏移:{dto5.Offset}, 转本地时间:{dto5.ToLocalTime()},转UTC时间:{dto5.ToUniversalTime()}");
输出结果:
DateTimeOffset:2023/7/27 8:40:25 +00:00, 偏移量:00:00:00, 转本地时间:2023/7/27 16:40:25 +08:00,转UTC时间:2023/7/27 8:40:25 +00:00
DateTimeOffset:2023/7/27 15:46:14 +08:00, 偏移量:08:00:00, 转本地时间:2023/7/27 15:46:14 +08:00,转UTC时间:2023/7/27 7:46:14 +00:00
DateTimeOffset:2023/7/27 7:46:14 +00:00, 偏移量:00:00:00, 转本地时间:2023/7/27 15:46:14 +08:00,转UTC时间:2023/7/27 7:46:14 +00:00
DateTimeOffset:2023/7/27 8:40:25 +08:00, 偏移量:08:00:00, 转本地时间:2023/7/27 8:40:25 +08:00,转UTC时间:2023/7/27 0:40:25 +00:00
DateTimeOffset:2023/7/27 8:40:25 -08:00, 偏移量:-08:00:00, 转本地时间:2023/7/28 0:40:25 +08:00,转UTC时间:2023/7/27 16:40:25 +00:00
可以看出,DateTimeOffset除了包含日期和时间之外,还包含相对于UTC时间的偏移量,因此不再需要Kind属性,就能区分出是UTC时间(如:dto1和dto3)还是本地时间(如:dto2、dto4和dto5),同时还能反馈时间所在的时区(如:dto2和dto4是东八区,dto5是西八区)。
最后得出结论:
DateTimeOffset和DateTime之间的确存在血缘关系,DateTimeOffset相当于是DateTime的一个包装,它除了具有DateTime的所有功能之外,还包含时区信息。如果你的系统不需要考虑时区问题或者只用UTC时间,那么DateTime就够用了。如果你的系统是全球化的,客户来自不同时区的不同国家,那么服务端就需要用DateTimeOffset来保存时间,这样客户端很容易将带有时区的时间字符串(如:"2023/7/27 8:40:25 +08:00")转成本地时间来显示。总而言之,小编认为DateTimeOffset功能比DateTime更强大、也更加灵活。微软官方建议用DateTimeOffset作为应用开发的默认时间类型。
参考资料:
彻底弄懂GMT、UTC、时区和夏令时 - 知乎 (zhihu.com)
c#:细说时区、DateTime和DateTimeOffset在国际化中的应用 - 知乎 (zhihu.com)
谈谈你最熟悉的System.DateTime[上篇] - Artech - 博客园 (cnblogs.com)
Compare types related to date and time | Microsoft Learn
DateTime和DateTimeOffset是同胞兄弟吗?的更多相关文章
- DateTime , DateTime2 ,DateTimeOffset 之间的小区别
闲来无事列了个表比对一下这3兄弟之间还是有一点差距的╮(╯_╰)╭ DateTime DateTime2 DateTimeOffset 日期范围 1753-01-01到 9999-12-31 00 ...
- C#中 DateTime , DateTime2 ,DateTimeOffset 之间的小区别 (转载)
闲来无事列了个表比对一下这3兄弟之间还是有一点差距的╮(╯_╰)╭ DateTime DateTime2 DateTimeOffset 日期范围 1753-01-01到 9999-12-31 00 ...
- DateTime还是DateTimeOffset?Now还是UtcNow?
(此文章同时发表在本人微信公众号"dotNET每日精华文章",欢迎右边二维码来关注.) 题记:新年第一篇文章,就来谈谈关于时间的简单技术问题:该用DateTime还是DateTim ...
- 第二节:比较DateTime和DateTimeOffset两种时间类型并介绍Quartz.Net中用到的几类时间形式(定点、四舍五入、倍数、递增)
一. 时间的类型 1. 背景 这里为什么要介绍时间类型呢,明明是定时调度篇,原因是在定时任务中,任务什么时间开始执行,什么时间结束执行,要用到各种各样的时间模式,虽然这不能算是一个复杂的问题,但在正式 ...
- 重学c#系列——datetime 和 datetimeoffset[二十一]
前言 简单介绍一下datetime和 datetimeoffset. 正文 了解一个国家的文化,就要了解一个国家的历史. 要了解datetimeoffset,那么很有必要了解一下datetime. 表 ...
- DateTime和DateTimeOffset的区别
1,DateTime 表示时间上的一刻,通常以日期和当天时间来表示. 2, DateTimeOffset 表示一个时间点,通常以相对于协调世界时(UTC)的日期和时间来表示. 3,下面是微软官方给出的 ...
- .NETFramework:DateTimeOffset
ylbtech-.NETFramework:DateTimeOffset 表示一个时间点,通常相对于协调世界时(UTC)的日期和时间来表示. 1.程序集 mscorlib, Version=4.0.0 ...
- 如何使用 System.Text.Json 序列化 DateTimeOffset 为 Unix 时间戳
在 .NET 中,日期和时间通常使用 DateTime 或 DateTimeOffset 来表示.这两种数据类型都可以表示日期和时间,但它们之间有一些明显的区别.DateTime 是不带时区信息的,而 ...
- 初试ASP.NET Web API/MVC API(附Demo)
写在前面 HTTP RESTful 创建Web API 调用Web API 运行截图及Demo下载 ASP.NET Web API是一个框架,可以很容易构建达成了广泛的HTTP服务客户端,包括浏览 ...
- ASP.NET Web API(MVC API)
ASP.NET Web API是一个框架,可以很容易构建达成了广泛的HTTP服务客户端,包括浏览器和移动设备.是构建RESTful应用程序的理想平台的.NET框架. 上面是微软对Web API给出 ...
随机推荐
- 访问nginx报错502日志:failed (13: Permission denied) while connecting to upstream
1.错误问题 nginx启动成功,但是访问nginx报错502.检查后台项目,使用IP+端口可以正常访问项目的,这说明项目启动成功了.那就是nginx的问题.检查了nginx.conf文件发现配置的反 ...
- Navicat Premium 16 安装教程
使用数据库时经常会使用到Navicat,码一个教程 转载自https://www.bilibili.com/read/cv21586676?spm_id_from=444.41.list.card_a ...
- #Powerbi 理解VAR函数
VAR意思即为变量,在编程语言中,变量是一个重要概念,DAX作为一种语言也有变量概念,利用VAR,我们可以缩短我们一些DAX语句的长度,更清晰的表达我们的度量值计算逻辑. 举例说明: 我们要计算一个产 ...
- iview中时间选择器组件改变日期格式
//改变视图的显示格式,但不会改变value的值的格式 format="yyyy-MM-dd" //改变value值的格式 @on-change="anZhuangDat ...
- Python这样读写Excel数据,这样简直不要太粗暴!
什么是xlrd&xlwt? xlrd和xlwt是Python语言中,读取和写入Excel数据的扩展工具.xlrd为xls文件read库,xlwt为xls文件write库.具体请看xlrd百度百 ...
- # 代码随想录算法训练营Day10 栈与队列| 理论基础 232.用栈实现队列 225. 用队列实现栈
栈与队列理论基础 队列是先进先出,栈是先进后出 关于栈的四个问题 C++中stack 是容器么? 我们使用的stack是属于哪个版本的STL? 我们使用的STL中stack是如何实现的? stack ...
- 人工智能导论——口罩佩戴检测详解(附带MTCNN论文精读)
人工智能导论--口罩佩戴检测详解(附带MTCNN论文精读) 一.问题重述 随着人类的科技不断进步,病毒也在随之更新迭代:在19年席卷全球的新冠肺炎疫情给人们的生活带来了极大的灾难,造成了无数的人因此失 ...
- springboot接入influxdb
转载请注明出处: 1.添加maven依赖 <dependency> <groupId>org.springframework.boot</groupId> < ...
- 一分钟学一个 Linux 命令 - mkdir 和 touch
前言 大家好,我是god23bin.欢迎来到<一分钟学一个 Linux 命令>系列,今天需要你花两分钟时间来学习下,因为今天要讲的是两个命令,mkdir 和 touch 命令.前一个命令是 ...
- Redis数据结构:高频面试题及解析
概述 Redis 是速度非常快的非关系型(NoSQL)内存键值数据库,可以存储键和五种不同类型的值之间的映射. 键的类型只能为字符串,值支持五种数据类型:字符串.列表.集合.散列表.有序集合. Red ...