推荐使用 DateTimeOffset.UtcNow.ToUnixTimeSeconds() 获取秒级 UTC 时间戳,因其自动处理时区与闰秒、避免浮点误差和 Kind 不明确问题,安全可靠至2106年。

用 DateTimeOffset.UtcNow.ToUnixTimeSeconds() 拿秒级 UTC 时间戳
这是最直接、最不容易出错的方式。C# 从 .NET Core 2.0 / .NET Framework 4.6 起支持 ToUnixTimeSeconds(),它内部自动处理时区偏移和闰秒忽略逻辑,结果就是标准的 Unix 时间戳(自 1970-01-01T00:00:00Z 起的秒数)。
常见错误是用 DateTime.Now.ToUniversalTime().Subtract(...) 手动算——容易漏掉毫秒截断、时区缓存问题,还可能因 DateTime.Kind 是 Unspecified 导致隐式本地转换。
-
DateTimeOffset.UtcNow明确带时区信息,不依赖Kind字段状态 - 返回
long,无溢出风险(到 2106 年前都安全) - 如果需要毫秒级,用
ToUnixTimeMilliseconds(),别自己乘 1000——精度会丢
为什么不用 DateTime.UtcNow 直接减 Epoch?
看似可行,但实际埋了三个坑:
-
DateTime.UtcNow的Kind是Utc,但new DateTime(1970,1,1)默认是Unspecified,直接Subtract可能触发意外转换(尤其在某些区域性设置下) - 手动计算要写
.TotalSeconds,结果是double,转long时可能因浮点误差截断错(比如 1712345678.999999 → 1712345678) - 没考虑 Windows 系统时钟可能有微小漂移,
DateTimeOffset底层调用更稳定的系统 API
示例对比:
DateTimeOffset now = DateTimeOffset.UtcNow; long ts = now.ToUnixTimeSeconds(); // ✅ 推荐
DateTime utc = DateTime.UtcNow; long bad = (long)(utc - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds; // ❌ 不稳定
时间戳转回可读的 UTC 时间:用 DateTimeOffset.FromUnixTimeSeconds()
和生成方向对应,反向还原也必须用 DateTimeOffset 系列方法,否则时区信息就丢了。
-
DateTimeOffset.FromUnixTimeSeconds(ts)返回带Utc偏移的实例,直接.DateTime或.ToString("o")就是标准 ISO 8601 UTC 格式 - 别用
DateTime.AddSeconds()手动加——同样面临Kind不明确、浮点误差、跨天进位等问题 - 如果输入是毫秒级时间戳,一定用
FromUnixTimeMilliseconds(),别除以 1000 再传给秒级方法(整数除法会截断)
跨平台和旧框架兼容要注意什么?
如果你还在维护 .NET Framework 4.5 或更老项目,ToUnixTimeSeconds() 不可用,得降级处理:
- 用
(DateTimeOffset.UtcNow - new DateTimeOffset(1970, 1, 1, TimeSpan.Zero)).TotalSeconds,然后Math.Floor()再转long—— 强制向下取整避免浮点误差 - 别用
DateTime替代DateTimeOffset,因为DateTimeOffset在 4.5+ 就已存在,且语义更准确 - Unity 用户注意:部分旧版 Mono 实现对
DateTimeOffset支持不全,建议封装一层运行时检测,fallback 到手工计算
真正容易被忽略的是:时间戳本身没有时区,但生成和解析它的上下文决定了是否“干净”。用错类型一次,后续所有日志对齐、API 交互、数据库存储都可能悄悄偏移几秒。











