请求中时区变更问题:发送Moment对象后日期异常变更的原因及解决方案
哈哈,这个坑我踩过好几次!咱们先搞清楚为啥会这样,再给你几个解决思路:
问题根源:时区序列化的默认行为差异
其实核心在于Moment对象的两种展示逻辑:
- 当你在控制台打印Moment对象时,它会自动转换为你的本地时区(这里是GMT+0200)来显示,所以你看到的是
Fri Oct 01 2021 00:00:00 GMT+0200——这是本地时区的时间。 - 但当你把Moment对象序列化为JSON时,默认会调用Moment的
toJSON()方法,这个方法的规则是将时间转换为UTC时区的ISO格式字符串。你的本地时间GMT+0200的00:00,减去2小时就是UTC的前一天22:00,所以就出现了"2021-09-30T22:00:00.000Z",日期自然就“跳”到前一天了。
解决方法:根据业务需求选对应方案
下面几种场景对应不同的解决方式,你可以根据后端的期望来选:
场景1:后端需要和你本地时区一致的时间/日期
不要直接序列化Moment对象,手动格式化你需要的格式:
- 如果只需要日期+时间(不带时区):用
momentObj.format('YYYY-MM-DDTHH:mm:ss'),得到的就是本地时区的"2021-10-01T00:00:00"。 - 如果需要带时区偏移的ISO格式(方便后端解析时区):用
momentObj.format('YYYY-MM-DDTHH:mm:ssZ'),输出"2021-10-01T00:00:00+02:00",后端能准确识别这是GMT+0200的时间。
示例代码:
const selectedDate = moment('2021-10-01', 'YYYY-MM-DD').startOf('day'); // 手动格式化后再序列化 const formattedDate = selectedDate.format('YYYY-MM-DDTHH:mm:ss'); console.log(JSON.stringify(formattedDate)); // "2021-10-01T00:00:00"
场景2:后端期望UTC时间,但要保证日期是你选择的那一天
如果业务上要求的是“选择的日期不管时区,在UTC里也是当天0点”,那你可以直接创建UTC时区的Moment对象:
// 直接基于选择的日期创建UTC时区的0点时间 const utcDate = moment('2021-10-01', 'YYYY-MM-DD').utc().startOf('day'); console.log(JSON.stringify(utcDate)); // "2021-10-01T00:00:00.000Z"
场景3:自定义Moment的toJSON行为(全局配置)
如果你不想每次都手动格式化,可以全局修改Moment的toJSON()方法,让它默认输出本地时区的格式:
moment.fn.toJSON = function() { return this.format('YYYY-MM-DDTHH:mm:ss'); }; // 之后直接序列化Moment对象就会用你定义的格式 console.log(JSON.stringify(selectedDate)); // "2021-10-01T00:00:00"
注意:这个方法是全局生效的,要确认项目里所有地方都适用这个规则再用。
内容的提问来源于stack exchange,提问作者MarWin
相关产品推荐
相关产品推荐

