使用Moment.js将ISO8601时间转成MMM月份+12小时制AM/PM格式报invalid date错误的解决方法
问题根因
触发invalid date的核心原因有两点:
- 当前拿到的原始时间字符串不符合标准ISO 8601 UTC格式规范:常规带毫秒的UTC时间结构为
YYYY-MM-DDTHH:mm:ss.sssZ,使用的字符串把「两位秒数+小数点+三位毫秒」的结构错写为「无小数点、三位数字直接接Z」,Moment的自动解析逻辑无法识别这类非标准结构,直接返回无效日期对象。 - Moment 1.x版本明确不推荐对非标准字符串做自动格式猜测,必须手动传入和实际输入字符串严格匹配的解析格式,才能稳定解析出有效日期对象。
实现步骤
1. 编写匹配输入结构的解析规则
针对输入串"2021-01-16T03:00:000Z"的实际结构,需要将对应解析格式作为moment方法的第二个参数传入,固定拆分规则,关闭自动猜测:
- 匹配
2021-01-16日期段:YYYY-MM-DD - 匹配中间的
T字符:用[T]转义,避免被识别为格式占位符 - 匹配
03:00时分段:HH:mm - 匹配后续紧跟的三位数字
000:SSS(对应毫秒位) - 匹配末尾的
Z字符:用[Z]转义,避免被识别为时区占位符
最终的解析格式串为:"YYYY-MM-DD[T]HH:mm:SSS[Z]"
2. 配置匹配目标结果的输出格式
需要输出的结果为Jan 16 - 3am,逐段对应Moment格式占位符:
Jan:3位英文月份缩写,对应占位符MMM16:两位日期值,对应占位符DD- 固定分隔符
-:直接写入格式串即可 3am:不补零的12小时制小时值,紧跟小写am/pm标识、无空格,对应占位符组合ha(其中h为不补零的12小时制小时,a为小写的上午/下午标识)
最终的输出格式串为:"MMM DD - ha"
3. 完整运行代码
const rawTimeStr = "2021-01-16T03:00:000Z"; // 传入解析格式,避免自动解析失败 const validDate = moment(rawTimeStr, "YYYY-MM-DD[T]HH:mm:SSS[Z]"); // 按目标格式输出 const output = validDate.format("MMM DD - ha"); // 运行结果即为 "Jan 16 - 3am"
注意事项
- 如果项目中加载了Moment的中文语言包,
MMM会输出中文月份,需要手动切回英文locale才能拿到Jan这类缩写,代码为moment.locale('en') - 如果可以调整上游接口的时间格式,建议将时间串修正为标准结构
2021-01-16T03:00:00.000Z,这类合规的标准ISO格式Moment可以直接自动解析,不需要手动传解析格式,跨环境兼容性更好。
内容的提问来源于stack exchange,提问作者seyet
相关产品推荐
相关产品推荐

