不是。DateTime.Now.Ticks 返回的是自公元1年1月1日00:00:00 UTC起的100纳秒计数,而非Unix时间戳(自1970-01-01T00:00:00Z起的秒或毫秒数),两者起点、单位和用途均不同。

DateTime.Now.Ticks 得到的是不是 Unix 时间戳?
不是。DateTime.Now.Ticks 返回的是从公元 1 年 1 月 1 日 00:00:00(UTC)开始的 100 纳秒单位计数,而 Unix 时间戳是自 1970-01-01T00:00:00Z 起的秒(或毫秒)数。直接用 Ticks 会得到一个约 63 亿亿级的大整数,完全不兼容标准接口。
常见错误现象:把 DateTime.Now.Ticks 当成毫秒时间戳传给前端或 API,结果服务端解析失败、时间错乱十几年。
- 正确做法是先转为
DateTimeOffset,再调用ToUnixTimeMilliseconds()(.NET Core 2.1+ / .NET 5+) - 旧框架(如 .NET Framework 4.7.2-)需手动计算:
(DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalMilliseconds - 注意:务必用
UtcNow或显式指定DateTimeKind.Utc,否则本地时区偏差会导致时间戳偏移
如何把毫秒时间戳转回 C# 的 DateTime?
Unix 毫秒时间戳本质是“自 1970-01-01 UTC 起经过的毫秒数”,转换关键在于起点对齐和时区处理。
- 推荐方式(.NET Core 2.1+):
DateTimeOffset.FromUnixTimeMilliseconds(ms).DateTime—— 返回DateTime,Kind 为Unspecified;若需明确 UTC,用.UtcDateTime - 兼容旧框架写法:
new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddMilliseconds(ms) - 别直接用
AddSeconds处理毫秒戳:容易因四舍五入丢精度(比如1717023600123除以 1000 是小数) - 如果输入可能为 null 或非法值(如负数、超大数),建议加校验,避免
ArgumentOutOfRangeException
为什么用 DateTimeOffset 而不是 DateTime 做时间戳转换?
DateTimeOffset 显式携带偏移量信息,能无歧义地表示某个时刻在世界任一时区的本地时间;而 DateTime.Kind 只有 Unspecified/Local/Utc 三种模糊状态,容易在序列化、跨系统传递时丢失上下文。
- API 接收时间戳时,应优先定义为
long或DateTimeOffset,而非DateTime - 数据库存储建议用
datetimeoffset类型(SQL Server)或带时区的timestamptz(PostgreSQL),避免后期时区修复成本 - JSON 序列化时,
DateTimeOffset默认输出 ISO 8601 带偏移格式(如"2024-05-30T12:00:00.123+08:00"),比DateTime更可靠
跨平台时间戳交互要注意什么?
前端 JavaScript 的 Date.now()、Java 的 System.currentTimeMillis()、Python 的 time.time() * 1000 都返回毫秒级 Unix 时间戳,但隐含前提都是「UTC 时间」。C# 侧一旦用了 DateTime.Now(本地时间)去算时间戳,就必然出错。
- 前后端约定必须统一使用毫秒 Unix 时间戳 + UTC 含义
- 调试时可用在线工具验证,例如输入
1717023600123,看是否对应预期 UTC 时间(2024-05-30 04:00:00.123 UTC) - 日志里打时间戳建议同时记录原始值和转换后的可读时间,便于排查时区混淆问题
实际项目中最容易被忽略的,是开发环境本地时区设置对 DateTime.Now 的干扰——哪怕代码写了 UtcNow,测试时若误用 Now 且没覆盖单元测试,上线后在服务器 UTC 时区下就会暴露问题。











