DateTime 或 DateTimeOffset 在 C# 中:开发者完整指南

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

引言:为什么日期会让你头疼?

如果你曾经用 C# 编写过代码,并且需要在莫斯科的服务器和纽约的客户端之间传递日期和时间,你肯定遇到过奇怪的 bug:“为什么显示的是明天?”,“这 3 个小时是从哪来的?”。熟悉吗?

在 .NET 中,有两个主要的日期处理工具:DateTime 和 DateTimeOffset。乍一看,它们很相似——都存储日期和时间。但它们之间的区别至关重要,选择错误可能会导致业务逻辑出现灾难性错误。

在本教程中,我们将通过实际示例深入分析 DateTime 与 DateTimeOffset,了解何时使用哪一个,并永远告别时区混淆。开始吧!



什么是 DateTime?(以及为什么它是一个陷阱)

DateTime 是一个存储 日期和时间 的结构。它从 .NET 的第一个版本就存在了。但它有一个特点:它不存储时区信息。更准确地说,它存储,但仅以 Kind 标志的形式存储:

  • DateTimeKind.Unspecified — 未指定时区(默认)。
  • DateTimeKind.Utc — UTC 时间。
  • DateTimeKind.Local — 系统的本地时间。

问题在于,这个标志只是信息。它不会自动转换时间。想象一下,你在莫斯科的服务器上将 DateTime 以 Kind = Local 保存到数据库。然后,你在符拉迪沃斯托克的服务器上读取这个日期。会发生什么?没错——程序看到 Kind = Local,就会认为这是符拉迪沃斯托克的本地时间。但实际上它是莫斯科时间。绝对的灾难。



// DateTime 问题示例DateTime moscowTime = new DateTime(2025, 3, 15, 14, 0, 0, DateTimeKind.Local);Console.WriteLine(moscowTime); // 15.03.2025 14:00:00 (假定这是 MSK)

// 如果这段代码在时区为 UTC+10(符拉迪沃斯托克)的服务器上运行// DateTime 将被解释为符拉迪沃斯托克的本地时间!// 这将导致 7 小时的错误。


什么是 DateTimeOffset?(开发者的救星)

DateTimeOffset 是一个更智能的结构,出现在 .NET Framework 3.5 中。它存储 日期、时间和相对于 UTC 的偏移量。偏移量是您的本地时间与 UTC 相差的小时和分钟数。

例如:2025-03-15 14:00:00 +03:00 — 这是莫斯科时间(UTC+3)。如果您将这个值传递给符拉迪沃斯托克(UTC+10)的服务器,.NET 会理解:“啊,这是 +03,所以 UTC 是 11:00。现在我可以轻松地将其转换为本地时间:21:00。” 没有魔法——纯粹的数学运算。



// DateTimeOffset 示例DateTimeOffset moscowOffset = new DateTimeOffset(2025, 3, 15, 14, 0, 0, TimeSpan.FromHours(3));Console.WriteLine(moscowOffset); // 15.03.2025 14:00:00 +03:00

// 现在,即使在符拉迪沃斯托克的服务器上,我们也知道准确的偏移量// 并且可以正确地为用户显示时间


关键区别:DateTime 与 DateTimeOffset

让我们将所有内容整理成一个清晰的表格。这将帮助您快速了解在特定情况下应该选择哪一个。



1. 时区信息存储

  • DateTime: 仅存储 Kind 标志(Unspecified, Utc, Local)。不存储偏移量本身。
  • DateTimeOffset: 存储相对于 UTC 的精确偏移量(例如,+03:00, -05:00)。


2. 值比较

  • DateTime: 按“裸”值进行比较。如果您有 10:00 UTC 和 10:00 MSK(UTC+3),那么 DateTime.Equals() 会说它们相等。尽管它们实际上是不同的时间点。
  • DateTimeOffset: 按 时间点(UTC)进行比较。10:00 UTC 和 13:00 MSK 是相同的

博客

书籍推荐