上周接了个需求,给海外客户做数据报表导出。本地测试一切正常,上线后客户反馈导出的 Excel 日期全乱了。

我第一反应是格式转换问题,检查了 moment 的格式化逻辑,没问题。然后怀疑是 Excel 解析的问题,换了几个库测试,还是不对。

真正诡异的是:只有部分日期错位,而且错位的规律毫无头绪。有的日期差了 8 小时,有的差了 16 小时,还有的完全正确。

排查了两天,把代码翻了个底朝天。最后在一个凌晨三点的测试中,突然意识到:我们的服务器部署在阿里云上海节点,但客户数据库用的是 AWS us-east-1。Node.js 的 new Date() 默认取的是服务器时区,而客户数据库存的是 UTC 时间,中间转换时我手动加了 8 小时偏移——但客户的业务数据本身就有不同时区的来源。

简单说,我在 UTC 转本地时加了 +8,但部分数据已经是本地时间格式存进去的,再加一次就错了。

解决方案其实不复杂:统一在数据库层处理时区,应用层只做透传,不碰时间计算。把 moment.tz 全部替换成标准 ISO 字符串处理。

但这件事给我最大的教训是:不要相信自己看到的时间。调试时我打印了 console.log(new Date()),显示的是北京时间,让我误以为数据也是北京时间。实际上数据库返回的已经是转换后的时间戳,我在应用层又转了一次。

现在我的团队规范里加了一条:任何时间处理必须显式声明时区,禁止依赖默认行为。

你们有没有遇到过类似的时区陷阱?我查了下,JavaScript 的 Date 对象在不同环境下的行为差异比想象中大得多。特别是涉及夏令时切换的日期,有些边缘 case 连 moment 都处理不好。

有踩过类似坑的老哥吗?或者你们团队是怎么规范时间处理的?