NX Blog - Sqlserver
type: channel
link: https://blog.nxsir.cn/index.php/tag/Sqlserver/
items: 关于那消失的 8 小时：Axios 与数据库 datetime 的合谋

关于那消失的 8 小时：Axios 与数据库 datetime 的合谋
type: item
date: 2026-02-07T17:43:19+08:00
description: 说实话，盯着代码看时差，比调 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) 再返回，否则这锅你永远背不完。