Moment与date-fns格式化Zulu日期时日期偏移一天的问题及解决
Zulu日期格式化后日期莫名加1天的问题及解决办法
问题描述
将Zulu格式日期(如2022-11-03T19:48:24Z)格式化为MM/dd/yyyy格式时,期望得到11/03/2022,但使用date-fns的format函数(代码如下)却得到11/04/2022,日期莫名加了一天。同时尝试Moment工具也存在同样问题。
使用的date-fns代码:
export function fDate( date: Date | string | number, template: string = 'MM/dd/yyyy' ) { return format(new Date(date), template); }
调用示例:
fDate('2022-11-03T19:48:24Z')
预期结果:11/03/2022,实际结果:11/04/2022
原因分析
核心问题是时区差异:
- Zulu格式的日期是UTC+0时区的时间,比如
2022-11-03T19:48:24Z代表UTC时间11月3日19点48分。 - 当你用
new Date()解析这个字符串时,JavaScript会自动将其转换为本地时区的时间。如果你的本地时区是东八区(UTC+8),那么这个时间加上8小时后就是本地时间11月4日3点48分。 - date-fns的
format函数和Moment的默认格式化都是基于本地时区的,所以最终输出的日期就变成了11/04/2022。
解决办法
方法1:使用date-fns的utcFormat函数(推荐)
date-fns提供了utcFormat函数,可以直接基于UTC时区格式化日期,避免本地时区转换:
import { utcFormat } from 'date-fns'; export function fDate( date: Date | string | number, template: string = 'MM/dd/yyyy' ) { return utcFormat(new Date(date), template); }
调用后会直接输出UTC时区的日期11/03/2022。
方法2:使用Moment的UTC解析方法
如果用Moment处理,需要用moment.utc()来解析日期,确保基于UTC时区格式化:
import moment from 'moment'; export function fDate(date: string | Date, template: string = 'MM/dd/yyyy') { return moment.utc(date).format(template); }
方法3:手动提取UTC日期字段拼接
不想依赖工具库的话,可以直接提取UTC时区的年、月、日字段,手动拼接成目标格式:
export function fDate(dateStr: string, template: string = 'MM/dd/yyyy') { const date = new Date(dateStr); // 注意月份是从0开始的,所以要+1 const month = String(date.getUTCMonth() + 1).padStart(2, '0'); const day = String(date.getUTCDate()).padStart(2, '0'); const year = date.getUTCFullYear(); return template.replace('MM', month).replace('dd', day).replace('yyyy', year.toString()); }
内容的提问来源于stack exchange,提问作者Yash
相关产品推荐
相关产品推荐

