JavaScript Date构造器解析“0”到“110”字符串的逻辑是什么?
关于JavaScript Date构造函数解析数字字符串的行为解释
核心结论
- 仅通过
const myNewDate = new Date(dateString)+_.isDate(myNewDate)完全不足以判定输入是合法日期:_.isDate仅校验变量是否为Date类型实例,就算构造出的是Invalid Date,_.isDate也会返回true。 - 你观察到的Chrome/Node与Firefox的行为差异,是因为ECMAScript规范没有对非标准日期格式的解析规则做强制要求:Chrome/Node用的V8引擎做了额外的兼容解析,Firefox没有实现该兼容逻辑,因此所有数字字符串都返回
Invalid Date,两种行为都符合规范要求。
逐现象解释底层逻辑
- 5-10月对应的UTC时间比其他月份少1小时:这是夏令时换算导致的正常现象,和日期解析逻辑无关,是日期从本地时区转UTC时间时,夏令时时段会自动调快1小时的特性。
- 0-12的数字字符串解析为2001年对应月份(0特殊为2000年1月):V8引擎将1-12区间的数字默认识别为月份,自动补全默认年份为2001年、日期为1号,数字0做了特殊处理默认解析为2000年1月1号。
- 13-31的数字字符串返回
Invalid Date:该区间的数字既不符合1-12的月份取值范围,也无法匹配到合理的月日组合,V8判定解析失败。 - 32-49的数字解析为20xx年、50-99的数字解析为19xx年:这是千年虫遗留的兼容规则,绝大多数编程语言的日期解析都有该逻辑:两位数年份≤49默认归属21世纪(补2000),≥50默认归属20世纪(补1900)。
- ≥100的数字直接作为年份,时分秒为运行时的本地时分秒:该区间的数字V8会直接识别为完整公元年份,自动补全为当年1月1日,1970年之前的日期V8会用运行时本地时间的时分秒补全后转UTC,因此你会看到固定的分秒数值。
正确的合法日期校验方案
不要依赖new Date的隐式字符串解析,按以下步骤实现:
- 先通过正则匹配输入字符串是否符合你预期的日期格式(如
YYYY-MM-DD、YYYY/MM/DD等) - 手动拆分出年、月、日、时、分、秒字段,用
new Date(year, month - 1, day, hour, minute, second)显式构造日期对象 - 校验
!isNaN(date.getTime())确认不是Invalid Date,再对比构造出的日期的年、月、日等字段是否和输入值完全一致,避免出现输入2023-02-30自动转为2023-03-02的问题
内容的提问来源于stack exchange,提问作者Luis Lobo Borobia
相关产品推荐
相关产品推荐

