说实话,盯着代码看时差,比调 Bug 累多了。
本来本地跑得好好的,17:00 点的数据存进数据库再取出来,直接变成了凌晨 01:00。这种 8 小时的凭空“瞬移”,常让我在屏幕前怀疑人生。
如果你也踩过这个坑,别急着在前端手动 +8,那只会让逻辑变得更乱。这事儿得从头捋。
自动转换的“冷箭”
讲真,很多人觉得 Axios 是原样传输,其实它调了 JSON.stringify。
当你的对象里包含 Date 类型时,JS 原型链里的 .toJSON() 方法会自动激活,效果等同于 .toISOString()。不管你本地电脑是什么时区,它都会被强行转成 UTC 零时区,结尾带个明显的 “Z”。
- 本地:
2026-02-07 17:00 (GMT+8) - 传给后端时:
"2026-02-07T09:00:00.000Z"
这个“Z”,就是一切混乱的开端。
数据库的“失忆症”
后端接收到带“Z”的字符串,解析为 C# 的 DateTime(Kind 为 Utc)时还没出问题。麻烦出在写入 SQL Server 或 MySQL 的 datetime 字段时。
datetime 就像一个只会记数字的记事本。 它只记下了 2026-02-07 09:00:00,至于时区,它根本没地方存。
读取时,噩梦闭环了:
- 后端读回数字,因为没有时区信息,C# 默认它为
Unspecified(未指定)。 - 回传给前端时,JSON 变成了没有“Z”的字符串。
- 浏览器看到没后缀的 ISO 字符串,默认按本地时间解析。
于是,原本是 UTC 的 9 点,被当作了本地的 9 点。这就是消失的 8 小时。
别再修补了,直接换零件
别去纠结怎么计算时差。与其在业务代码里打补丁,不如从数据定义上直接解决。
| 类型 | 存储逻辑 | 读取结果 |
|---|---|---|
| DateTime | 只存数字,丢弃偏移量 | 时区全靠猜,极易出错 |
| DateTimeOffset | 存数字 + 偏移量(如 +00:00) | 原生支持时区,两端对齐 |
最终建议:
如果你不想改业务代码,最快的方法就是把数据库字段改成 DateTimeOffset。你会发现数据库里多出了 +00:00 的后缀,前端解析时再也不会产生“时空错位”。
如果你非要守着 datetime 不放,那后端查出来后,必须手动执行 DateTime.SpecifyKind(time, DateTimeKind.Utc) 再返回,否则这锅你永远背不完。
评论 (0)