应使用 DateTimeOffset.UtcNow.ToUnixTimeSeconds() 获取 Unix 时间戳,因其自动处理 UTC 时区,避免 DateTime.Now 减法导致的本地时区偏差;毫秒级则用 ToUnixTimeMilliseconds();旧框架可用 DateTimeOffset.UtcNow 手动计算并显式指定 TimeSpan.Zero。

直接用 DateTimeOffset.UtcNow.ToUnixTimeSeconds(),别自己算。这是最安全、最不易出错的方式,尤其在跨时区、微服务或与前端/第三方系统交互时。
为什么不能用 DateTime.Now 减 1970 年?
常见错误是写成:DateTime.Now - new DateTime(1970, 1, 1)。这会导致时间戳基于本地时区(比如中国是 UTC+8),结果比标准 Unix 时间戳大 28800 秒(8 小时),和其他系统对接时必然错乱。
-
DateTime.Now.Kind是Unspecified或Local,参与运算时不会自动转 UTC,容易隐式误用 - 手动构造的
new DateTime(1970, 1, 1)默认是Unspecified,和Now相减会触发模糊时区转换逻辑 - 即使加了
DateTimeKind.Utc,也要确保两边都显式指定,否则仍可能被 CLR 暗中修正
ToUnixTimeSeconds() 和 ToUnixTimeMilliseconds() 怎么选?
看下游系统要求:HTTP API、数据库字段、日志规范通常明确指定是秒级还是毫秒级。二者不可混用,也不能靠自己乘除转换。
- 秒级用
DateTimeOffset.UtcNow.ToUnixTimeSeconds()—— 返回long,范围到 2106 年,足够长期使用 - 毫秒级用
DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()—— 同样返回long,精度更高,但数值更大 - 别用
DateTime.UtcNow.Ticks / 10_000_000再减常量(如 621355968000000000)—— 容易溢出、可读性差、且Ticks是 .NET 内部计时单位,不是设计给人直接算的 - 别对毫秒级时间戳做
/ 1000后喂给秒级解析方法 —— 整数除法会截断小数部分,导致时间偏移 1 秒
.NET Framework 4.5 或更老版本怎么办?
如果项目还卡在旧框架上,ToUnixTimeSeconds() 不可用,必须降级处理,但仍有简洁可靠写法:
- 用
DateTimeOffset.UtcNow而非DateTime.Now,它自带明确的Kind和时区信息 - 手动计算:
(long)(DateTimeOffset.UtcNow - new DateTimeOffset(1970, 1, 1, 0, 0, 0, TimeSpan.Zero)).TotalSeconds - 注意:必须用
TimeSpan.Zero显式指定 UTC 偏移,不能省略第三个参数,否则构造出的DateTimeOffset可能带本地偏移 - 避免使用
DateTime类型做减法再转TimeSpan.TotalSeconds—— 一旦Kind不一致,结果不可控
真正容易被忽略的不是“怎么写”,而是“谁来负责时区对齐”。时间戳本质是事件发生的 UTC 刻度,只要生成端统一用 DateTimeOffset.UtcNow 系列方法,消费端用对应 FromUnixTimeXXX 解析,中间就不再需要任何时区干预。一念之差用错类型,排查成本远高于写对那一行代码。










