边界在哪里?
32 位有符号整数范围是 −2,147,483,648 到 2,147,483,647。把它解释为 Unix 秒时,正数上限对应 2038-01-19T03:14:07Z;再加一秒就会在这种表示中溢出。
哪些系统需要检查?
旧操作系统、嵌入式设备、数据库字段和二进制协议仍可能使用 32 位有符号秒。64 位时间戳或合适的日期类型能把实际边界推到普通应用寿命之外,但必须确认完整数据链路都已升级。
如何测试?
应在边界两侧选取数值,穿过解析器、存储、API 序列化、客户端运行时和报表工具做端到端测试。现代应用服务器并不能自动保护旧数据库列或设备协议。
不只看 2038 年
还要检查毫秒字段的整数范围、JavaScript 安全整数和第三方 API 的日期限制。不同单位与类型可能在不同年份到达边界。
上限附近的三个数值
| Unix 秒 | UTC 日期 |
|---|---|
2147483646 | 2038-01-19 03:14:06 |
2147483647 | 2038-01-19 03:14:07 |
2147483648 | 2038-01-19 03:14:08 |
第三个值本身完全合法,只是超出了有符号 32 位整数的容量,不代表 Unix 时间定义结束。可在时间戳转日期工具中手动选择秒核对。
有符号 32 位整数范围为 −2,147,483,648 至 2,147,483,647。旧系统如果溢出回绕而非拒绝写入,下一个值可能变成负数,显示到 1901 年。具体行为取决于语言、操作系统和存储实现。
不只检查数据库列
检查数据库字段、驱动绑定、API 字段类型、序列化以及应用变量。只把数据库列改大,无法解决客户端或嵌入式设备继续强制转换为 32 位整数的问题。测试边界两侧的值,写入后再读取,核对整数本身,不能只看格式化日期是否像正常结果。
选择整个数据链路都支持的宽整数或日期类型。无符号 32 位秒数虽然有更晚的上限,但不支持负日期,也没有解决所有协议兼容问题。
与浏览器和 JavaScript 的限制分开看
2038 问题针对有符号 32 位的秒。JavaScript 安全整数上限、浏览器日期范围是另外的限制。相同时刻的毫秒、微秒、纳秒数值更大,不能因为日期还没到 2038 就认为精度一定安全。
秒与毫秒指南解释单位选择;批量转换器可以检查迁移文件中的日期,但无法检查或修改外部系统的数据类型。