引言:为什么 Unix 时间戳不仅仅是一个数字
\n每个与 API、数据库或日志打交道的开发者,迟早都会遇到 Unix 时间戳。它是一个整数(或浮点数),表示自 1970 年 1 月 1 日 00:00:00 UTC 以来经过的秒数——即所谓的 Unix 纪元。
\n但是,当你在服务器响应中看到数字 1719878400 时,你的大脑无法立刻说出:“啊,这是 2024 年 7 月 2 日”。我们需要将其转换为熟悉的 DateTime。反之亦然——将日期保存为时间戳以便传输。
在 Stack Overflow 上,问题 “如何将 Unix 时间戳转换为 DateTime 以及反向转换?” 获得了数十万次浏览。这意味着即使是经验丰富的 C# 开发者有时也会在细节上感到困惑。在本文中,我们不仅会提供现成的解决方案,还会深入 底层:剖析 DateTime、DateTimeOffset、时钟周期和时区是如何工作的。
Unix 时间戳到底是什么?
\n在编写代码之前,让我们先统一术语。Unix 时间戳 是从 UTC 时间 1970 年 1 月 1 日午夜开始经过的秒数(有时是毫秒数)。重要的是:这是一个绝对的时间点,不依赖于时区。正因如此,它在分布式系统中非常方便使用。
\n在 C# 中,我们使用两种主要类型:
\n- \n
DateTime— 经典类型,可以是 UTC 时间,也可以是本地时间(通过Kind属性)。 \n DateTimeOffset— 更现代的类型,显式存储与 UTC 的偏移量。推荐用于新项目。 \n
在底层,DateTime 存储自公元 0001 年 1 月 1 日以来的 时钟周期 数(100 纳秒间隔)。而 Unix 时间戳只是自 1970 年以来的秒数。要在两者之间转换,需要计算这两个纪元之间的差值。
Unix 时间戳与 DateTime 的相互转换——基本方法
\n从 .NET Framework 4.6 和 .NET Core 开始,C# 中引入了内置方法,使生活更简单。让我们来看看它们。
\n\n1. 从 Unix 时间戳(秒)到 DateTime
\n最简单的方法是使用 DateTimeOffset.FromUnixTimeSeconds()。它返回一个 DateTimeOffset,然后可以将其转换为 DateTime。
long unixTimestamp = 1719878400; // 2024 年 7 月 2 日, 00:00:00 UTC\n\n// 获取 DateTimeOffset\nDateTimeOffset dateTimeOffset = DateTimeOffset.FromUnixTimeSeconds(unixTimestamp);\n\n// 转换为 DateTime (UTC)\nDateTime utcDateTime = dateTimeOffset.UtcDateTime;\n\nConsole.WriteLine(utcDateTime); // 02.07.2024 0:00:00\n如果你需要本地时间(例如,向用户显示),请使用 dateTimeOffset.LocalDateTime。但要小心:本地时间取决于服务器或计算机的设置。
2. 从 DateTime 到 Unix 时间戳
\n反向转换——通过 DateTimeOffset 的 ToUnixTimeSeconds() 方法。
DateTime utcDateTime = new DateTime(2024, 7, 2, 0, 0, 0, DateTimeKind.Utc);\n\n// 创建显式指定 UTC 的 DateTimeOffset\nDateTimeOffset dateTimeOffset = new DateTimeOffset(utcDateTime);\n\nlong unixTimestamp = dateTimeOffset.ToUnixTimeSeconds();\n\nConsole.WriteLine(unixTimestamp); // 1719878400\n至关重要的是:在创建要转换的 DateTime 时,始终指定 DateTimeKind.Utc。如果不这样做,DateTimeOffset 会认为时间是本地时间,你将得到错误的时间戳——会偏移你的时区。
3. 处理毫秒
\n有时时间戳以毫秒为单位传递(例如,来自 JavaScript)。为此,请使用