JavaScript处理1700-01-01及更早日期时的解析异常问题
问题成因
这不是JavaScript的Bug,是两个客观规则共同作用的结果:
- 近现代之前的时区偏移规则不统一
现代时区的标准整偏移(比如东8区固定+8小时)是19世纪后期才逐步统一推行的,对于更早的历史日期,JavaScript的Date对象会自动适配对应时期的本地平均时间(LMT),不同地区的LMT和现在的标准时区偏移存在几秒到几十分钟的差值,这个差值只会出现在近代以前的日期上,2000年这类近现代日期用统一的标准时区偏移,所以不会有问题。 toString()序列化日期的方式不可靠Date.prototype.toString()的输出是和本地时区绑定的非标准化人类可读字符串,ECMAScript规范没有强制要求不同引擎对这类非ISO格式的旧日期字符串保持一致的解析逻辑,对于带历法转换、LMT偏移的旧日期,解析时很容易出现偏移误差。
另外1700年前后的解析误差也和儒略历转格里高利历的历史遗留有关,不同地区切换格里高利历的时间不同,JS引擎在处理对应时期的日期时会自动计算历法差值,进一步加大了非标准字符串解析的误差概率。
修复方案
完全规避这类问题的核心是不要用toString()做日期序列化,选以下任意一种标准化序列化方案即可:
- 序列化时存储时间戳:直接调用
testDate.getTime()拿到数字格式的时间戳,解析时直接new Date(时间戳数值),全程没有字符串解析逻辑,100%不会出现日期偏移 - 序列化时存储标准ISO格式字符串:调用
testDate.toISOString()输出UTC时间的标准ISO字符串,所有JS引擎对该格式的解析逻辑完全符合规范,不会出现误差
内容的提问来源于stack exchange,提问作者Cole Medin
相关产品推荐
相关产品推荐

