DateTime 和 DateTimeOffset 是同胞兄弟吗?

322 阅读4分钟

前言

在日常的 C# 开发中,DateTime 是最常被使用的时间类型。然而,当有一天你遇到 DateTimeOffset,可能会像小编一样感到疑惑:它到底是什么?和 DateTime 又是什么关系?它们之间是否真的“血脉相连”?

为了解开这些谜团,本文将带你深入了解 DateTimeDateTimeOffset 的本质区别与联系。我们将从基本的时间概念出发,逐步剖析这两个类的结构、用途和使用场景,并通过代码示例帮助你更好地理解它们在实际开发中的应用。

一、先了解几个时间概念

在深入 DateTimeDateTimeOffset 之前,先来了解几个关键的时间术语:

  • GMT(Greenwich Mean Time):格林威治标准时间,1972 年前是世界时间的标准。

  • UTC(Coordinated Universal Time):协调世界时,是当前全球通用的标准时间。

  • TimeZone(时区):将地球划分为 24 个时区,每个时区相差 1 小时。

举个例子

北京位于东八区,与 UTC 时间相差 +8 小时。当你早上 8 点起床时,伦敦可能还是午夜。

二、DateTime:时间的基本表示

DateTime 表示一个日期和时间值。它通过一个只读属性 Kind 来标识这个时间是本地时间、UTC 时间,还是未指定类型。

public enum DateTimeKind
{
    Unspecified = 0, // 未指定
    Utc = 1,         // UTC 时间
    Local = 2        // 本地时间
}

常见用法示例

DateTime dt1 = new DateTime(2023, 7, 27, 8, 40, 25); 
Console.WriteLine($"DateTime:{dt1}, 时间类型:{dt1.Kind}, 转本地时间:{dt1.ToLocalTime()},转UTC时间:{dt1.ToUniversalTime()}");

DateTime dt2 = DateTime.Now; 
Console.WriteLine($"DateTime:{dt2}, 时间类型:{dt2.Kind}, 转本地时间:{dt2.ToLocalTime()},转UTC时间:{dt2.ToUniversalTime()}");

DateTime dt3 = DateTime.UtcNow; 
Console.WriteLine($"DateTime:{dt3}, 时间类型:{dt3.Kind}, 转本地时间:{dt3.ToLocalTime()},转UTC时间:{dt3.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 缺乏对时区的明确支持,无法直接判断一个时间属于哪个时区,除非它是 UTC 时间。

三、DateTimeOffset:时间 + 时区偏移量

DateTimeOffset 是对 DateTime 的增强,它不仅包含日期和时间信息,还包含一个 TimeSpan 类型的 Offset 属性,表示相对于 UTC 的偏移量。

常见用法示例

DateTimeOffset dto1 = new DateTimeOffset(2023, 7, 27, 8, 40, 25, TimeSpan.Zero);
Console.WriteLine($"DateTimeOffset:{dto1}, 时间偏移:{dto1.Offset}, 转本地时间:{dto1.ToLocalTime()},转UTC时间:{dto1.ToUniversalTime()}");

DateTimeOffset dto2 = DateTimeOffset.Now;
Console.WriteLine($"DateTimeOffset:{dto2}, 时间偏移:{dto2.Offset}, 转本地时间:{dto2.ToLocalTime()},转UTC时间:{dto2.ToUniversalTime()}");

DateTimeOffset dto3 = DateTimeOffset.UtcNow;
Console.WriteLine($"DateTimeOffset:{dto3}, 时间偏移:{dto3.Offset}, 转本地时间:{dto3.ToLocalTime()},转UTC时间:{dto3.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 包含完整的时区偏移信息(如:+08:00)

  • 不再依赖 Kind 属性,可以直接判断时间来源

  • 更适合全球化系统、跨时区数据处理

结论

它们是"同胞兄弟"吗?

是的,它们是"同胞兄弟"

  • DateTimeOffset 可以看作是 DateTime 的"增强版"或"包装类”。

  • 它继承了 DateTime 的全部功能,并额外增加了时区偏移信息。

  • 如果你的系统只需要处理本地时间或 UTC 时间,DateTime 足够使用。

  • 如果你的系统需要处理全球化、跨时区的时间数据,推荐使用 DateTimeOffset

总结

DateTimeDateTimeOffset 都是 C# 中用于处理时间的核心类型。它们之间虽然“血脉相连”,但适用场景不同:

  • DateTime 更适合本地化、单一时区的应用。

  • DateTimeOffset 更适合全球化、需要精确时区信息的系统。

在开发中,微软官方也建议优先使用 DateTimeOffset,因为它更准确、更灵活,尤其在处理跨时区数据时,能有效避免歧义和错误。

关键词

DateTime、DateTimeOffset、时间处理、时区、UTC、GMT、TimeZone、C#、.NET、时间偏移、Kind、TimeSpan、全球化、本地化、UTC时间、本地时间、偏移量、DateTime.Now、DateTime.UtcNow、DateTimeOffset.Now、DateTimeOffset.UtcNow

最后

如果你觉得这篇文章对你有帮助,不妨点个赞支持一下!你的支持是我继续分享知识的动力。如果有任何疑问或需要进一步的帮助,欢迎随时留言。

也可以加入微信公众号 [DotNet技术匠] 社区,与其他热爱技术的同行一起交流心得,共同成长!

优秀是一种习惯,欢迎大家留言学习!

作者:天行健君子以自强

出处:cnblogs.com/fengjq/p/17583940.html

声明:网络内容,仅供学习,尊重版权,侵权速删,歉意致谢!