JavaScript datetimeZone时区日期格式moment验证失败解决方案
问题原因
之前使用的格式串YYYY-MM-DDTHH:mm:ss.SSSZ校验失败是两个占位符不匹配导致的:
SSS是moment中3位毫秒的占位符,只能匹配小数点后3位数字,传入的日期带6位小数秒(微秒级),超出占位符匹配长度Z是moment中无冒号时区偏移的占位符,仅能匹配+0300这类格式,传入的+03:00是带冒号的时区格式,无法被Z匹配
可行解决方案
方案1:修正moment格式串(推荐)
将格式串调整为YYYY-MM-DDTHH:mm:ss.SSSSSSZZ即可通过严格校验,调整点说明:
- 用6位小数秒占位符
SSSSSS匹配6位微秒值,moment解析时会自动取前3位作为毫秒计算,不影响后续时间运算 - 用
ZZ占位符匹配带冒号的时区偏移格式,适配+03:00这类写法
如果需要同时兼容之前使用的两种日期格式,直接把三个格式放在数组里传入moment即可,示例:
// 严格校验模式下同时兼容三类日期格式 const valid = moment(yourDateStr, [ 'YYYY-MM-DD', 'YYYY-MM-DDTHH:mm:ss', 'YYYY-MM-DDTHH:mm:ss.SSSSSSZZ' ], true).isValid()
方案2:关闭moment严格校验模式
如果业务上不需要强校验每一位的格式匹配(比如小数秒可能是3位、6位,时区可能带冒号也可能不带),可以去掉严格校验参数,moment会自动容错匹配,写法更简单:
// 非严格校验,自动兼容不同位数小数秒、不同时区写法 const valid = moment(yourDateStr, [ 'YYYY-MM-DD', 'YYYY-MM-DDTHH:mm:ss', 'YYYY-MM-DDTHH:mm:ss.SSSZ' ]).isValid()
注意:非严格模式下部分格式偏差较大的字符串也可能被判定为合法,适合对格式精度要求不高的场景。
正则校验实现
完全可以通过正则实现该类格式的校验,以下正则可同时兼容提到的三类日期格式:
const dateValidateReg = /^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])(T([01]\d|2[0-3]):[0-5]\d:[0-5]\d(\.\d{6})?([+-]([01]\d|2[0-3]):[0-5]\d|Z)?)?$/
正则校验的注意事项:
- 仅能校验格式合法性,无法识别逻辑非法的日期(比如
2024-02-30、2024-04-31这类格式符合规则但实际不存在的日期,正则会判定为合法) - 如果需要做逻辑合法性校验,可以在正则匹配通过后,再把字符串传入Date或者moment解析,判断解析后的时间是否和输入值一致即可。
内容的提问来源于stack exchange,提问作者Alex
相关产品推荐
相关产品推荐

