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给出 ...
随机推荐
- 深度学习-07(图像分类、常用数据集、利用CNN实现图像分类、图像分类优化)
文章目录 深度学习-07(PaddlePaddle图像分类) 图像分类概述 概述 什么是图像分类 图像分类粒度 图像分类发展历程 图像分类问题的挑战 常用数据集介绍 MNIST数据集 CIFAR10数 ...
- 禁用Chrome浏览器Websocket
前言:最近遇到关于Websocket的相关测试,推荐一个禁用Chrome浏览器Websocket的扩展插件 一.下载使用 1.https://github.com/arthepsy/chrome-di ...
- AI 绘画基础 - 细数 Stable Diffusion 中的各种常用模型 【🧙 魔导士装备图鉴】
AI 绘画新手魔导士在刚开始玩 Stable Diffusion 时总会遇到各种新的概念,让人困惑,其中就包括各种模型和他们之间的关系. 魔法师入门得先认识各种法师装备(各种模型),让我们遇到问题知道 ...
- [python] Python类型提示总结
Python3.5 版本引入了类型提示(Type Hints),它允许开发者在代码中显式地声明变量.函数.方法等的类型信息.这种类型声明不会影响 Python 解释器的运行,但可以让 IDE 和静态分 ...
- LOTO示波器如何测试阻抗的频响曲线
LOTO示波器如何测试阻抗的频响曲线 模块的输入输出端口,在电路分析上,一般简单表征为电阻来进行计算和分析.但多数情况下,这些端口并不是纯电阻的特性,更精确一些,它可能是电阻电容以及电感的组合,表现为 ...
- 不要轻易尝试 weexplus open as
昨日使用 weexplust publish android 编译apk, 出现了一大堆错 FAILURE: Build failed with an exception. * What went w ...
- 基于.NetCore开源的Windows的GIF录屏工具
推荐一个Github上Start超过20K的超火.好用的屏幕截图转换为 GIF 动图开源项目. 项目简介 这是基于.Net Core + WPF 开发的.开源项目,可将屏幕截图转为 GIF 动画.它的 ...
- web自动化01-环境搭建
1.自动化测试是什么? 借助工具实现 借助代码编写脚本实现 2.自动化测试需要掌握那些? web自动化测试基础 移动端自动化基础 pytest自动化测试框架 po设计模式 数据驱动 日志模块使用 自 ...
- Kubernetes 研究笔记
Kubernetes 研究笔记 在接下来的这篇笔记中,我将会介绍 Kubernetes 这一强大的容器编排工具,并学习其基本使用方法.该笔记将会被存储在https://github.com/owlma ...
- python 学习 ---函数(带参数)
函数式编程最重要的是增强代码的重用性和可读性 1 def 函数名(参数): 2 3 ... 4 函数体 5 ... 函数的定义主要有如下要点: def:表示函数的关键字 函数名:函数的名称,日后根据函 ...