如何修复React Date Picker搭配Redux使用时的时间偏差与格式报错问题
问题原因
- 时差问题本质是时区转换导致:你本地时区为GMT+4,选中的日期是本地时间当月1日0点,转UTC时间后会自动偏移为前一天20点,Redux序列化Date对象时会默认转为UTC格式的ISO字符串,因此出现日期、月份偏移。
date.format is not a function报错原因:Redux存储的是序列化后的ISO字符串,字符串原型链上没有format方法,只有Date对象或日期库封装的实例才能调用format方法。
解决方案
方案一(更推荐,无序列化与时区坑):直接存储格式化后的月份年份字符串
选中日期时直接转为MMM yyyy格式的纯字符串存入Redux,回显时再将字符串解析为Date对象传给组件即可,示例代码如下(以date-fns日期库为例,moment.js逻辑一致):
import { format, parse } from 'date-fns'; <DatePicker // 回显时把Redux中存的字符串解析为Date对象 selected={passenger?.passportExp ? parse(passenger.passportExp, 'MMM yyyy', new Date()) : null} onChange={(date) => { // 选中时直接格式化为目标字符串存入Redux,避开Date序列化问题 const formattedDate = format(date, 'MMM yyyy'); modifyPassenger(index, { passportExp: formattedDate }); }} maxDate={new Date(new Date().getFullYear(), new Date().getMonth() + 1, 0)} showMonthYearPicker dateFormat="MMM yyyy" onFocusChange={({ focused }) => this.setState({ passportExp: focused })} />
方案二:存储UTC标准化的日期
如果业务需要存储日期格式的值,可以在存入前主动将日期转为UTC时区的当月1号,避免序列化后月份偏移:
<DatePicker selected={passenger?.passportExp ? new Date(passenger.passportExp) : null} onChange={(date) => { // 主动构造UTC时区的当月1号,序列化后不会出现月份偏移 const utcDate = new Date(Date.UTC(date.getFullYear(), date.getMonth(), 1)); modifyPassenger(index, { passportExp: utcDate }); }} maxDate={new Date(new Date().getFullYear(), new Date().getMonth() + 1, 0)} showMonthYearPicker dateFormat="MMM yyyy" onFocusChange={({ focused }) => this.setState({ passportExp: focused })} />
内容的提问来源于stack exchange,提问作者zaid
相关产品推荐
相关产品推荐

