c#没有内置时间戳类型,获取unix时间戳必须用datetime.utcnow或datetimeoffset.utcnow,并注意时区、精度和kind属性;错误使用datetime.now或忽略utcnow会导致结果偏差。

直接说结论:C# 没有内置的“时间戳”类型,所谓“获取当前时间戳”本质是把 DateTime.UtcNow 转成 Unix 时间戳(秒或毫秒整数),关键在时区和精度选择——用错 DateTime.Now 或漏掉 .Ticks 除法会得到错误值。
为什么 DateTime.Now 不能直接当 Unix 时间戳用
Unix 时间戳定义为“自 1970-01-01 00:00:00 UTC 起经过的秒数”,而 DateTime.Now 是本地时区时间,且其 .Ticks 基于 0001-01-01。直接减去 Unix 起始时间再除 TicksPerSecond 会因时区偏移出错。
- 错误写法:
DateTime.Now.Subtract(new DateTime(1970, 1, 1)).TotalSeconds→ 结果含本地时区偏移,比如东八区会多 +28800 秒 - 正确前提:必须用
DateTime.UtcNow,确保基准统一为 UTC - 注意
DateTimeKind:即使值相同,DateTime实例的Kind属性为Unspecified时,ToUniversalTime()可能误转
获取当前秒级/毫秒级 Unix 时间戳的可靠写法
推荐用 DateTimeOffset,它自带 UTC 意识,比手动处理 DateTime 更安全:
// 秒级时间戳(long) long timestampSec = DateTimeOffset.UtcNow.ToUnixTimeSeconds(); <p>// 毫秒级时间戳(long) long timestampMs = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();</p><p>// 兼容 .NET Core 2.1+ / .NET 5+;旧版本需手动计算 </p>
- 如果项目还在用 .NET Framework 4.7.2 或更早,没有
ToUnixTimeSeconds,则用:(long)(DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds - 务必用
DateTimeKind.Utc显式指定起始时间的种类,避免隐式转换 - 不要用
TotalMilliseconds然后取整——浮点转 long 可能因精度丢失导致毫秒值偏差 1
DateTime 与时间戳互转时的典型坑
反向转换(时间戳 → DateTime)同样要注意时区和精度截断问题:
- 从秒级时间戳转
DateTime:DateTimeOffset.FromUnixTimeSeconds(timestampSec).UtcDateTime→ 得到DateTimeKind.Utc实例;若用.DateTime会返回本地时区时间,容易混淆 - 毫秒级时间戳转
DateTime时,FromUnixTimeMilliseconds返回的是精确到毫秒的DateTimeOffset,但DateTime的最小单位是 100 纳秒(即 0.1 微秒),所以不会丢精度 - 警惕
DateTime.Parse("1609459200")这类写法——字符串无法被识别为时间戳,会抛FormatException - 数据库存储场景:SQL Server 的
DATETIME2支持纳秒级,但 Unix 时间戳本身无时区信息,存之前务必确认业务是否需要保留原始 UTC 意图
真正麻烦的不是换算公式,而是每次调用时下意识选错 Now 还是 UtcNow、忽略 Kind 属性、或在跨系统传时间戳时没约定好单位(秒 vs 毫秒)。这些地方一错,排查时往往要翻日志比对三四个服务的时间输出才能定位。










