Chrome 88以下版本Day.js识别DST异常问题求助
Day.js在Chrome 88及以下版本夏令时识别问题的解决方案
我们计划引入Day.js处理夏令时(DST),该工具在现代浏览器中表现正常,但在Chrome 88及以下版本的旧浏览器中无法正确识别DST。测试用的React应用代码如下:
import { useState, useEffect } from 'react'; import dayjs from 'dayjs'; import utc from 'dayjs/plugin/utc'; import timezone from 'dayjs/plugin/timezone'; dayjs.extend(utc); dayjs.extend(timezone); const defaultTimezone = "Africa/Cairo"; const events = [ { date: '2024-04-20', time: '20:00', description: 'Event 1', timezone: defaultTimezone }, { date: '2024-04-30', time: '20:00', description: 'Event 2', timezone: defaultTimezone }, { date: '2024-06-05', time: '20:00', description: 'Event 3', timezone: defaultTimezone }, { date: '2024-09-20', time: '20:00', description: 'Event 4', timezone: defaultTimezone }, { date: '2024-10-20', time: '20:00', description: 'Event 5', timezone: defaultTimezone }, { date: '2024-11-20', time: '20:00', description: 'Event 6', timezone: defaultTimezone }, ]; function App() { const [formattedEvents, setFormattedEvents] = useState([]); useEffect(() => { const formattedEvents = events.map(event => { const cairoDateTime = dayjs.tz(`${event.date}T${event.time}`, event.timezone); const berlinDateTime = cairoDateTime.clone().tz('Europe/Berlin'); const formattedCairoDateTime = cairoDateTime.format('YYYY-MM-DD HH:mm:ss'); const formattedBerlinDateTime = berlinDateTime.format('YYYY-MM-DD HH:mm:ss'); return { ...event, cairoDateTime: formattedCairoDateTime, berlinDateTime: formattedBerlinDateTime }; }); setFormattedEvents(formattedEvents); }, []); return ( <div className="App"> <header className="App-header"> <h2>Events</h2> <ul> {formattedEvents.map((event, index) => ( <li key={index}> {event.description}: <ul> <li>Cairo Time: {event.cairoDateTime} ({event.timezone})</li> <li>Berlin Time: {event.berlinDateTime} (Europe/Berlin)</li> </ul> </li> ))} </ul> </header> </div> ); } export default App;
输出差异
现代浏览器(符合预期)
Events Event 1: Cairo Time: 2024-04-20 20:00:00 (Africa/Cairo) Berlin Time: 2024-04-20 20:00:00 (Europe/Berlin) Event 2: Cairo Time: 2024-04-30 20:00:00 (Africa/Cairo) Berlin Time: 2024-04-30 19:00:00 (Europe/Berlin) Event 3: Cairo Time: 2024-06-05 20:00:00 (Africa/Cairo) Berlin Time: 2024-06-05 19:00:00 (Europe/Berlin) Event 4: Cairo Time: 2024-09-20 20:00:00 (Africa/Cairo) Berlin Time: 2024-09-20 19:00:00 (Europe/Berlin) Event 5: Cairo Time: 2024-10-20 20:00:00 (Africa/Cairo) Berlin Time: 2024-10-20 19:00:00 (Europe/Berlin) Event 6: Cairo Time: 2024-11-20 20:00:00 (Africa/Cairo) Berlin Time: 2024-11-20 19:00:00 (Europe/Berlin)
Chrome 88及以下版本(DST识别错误)
Events Event 1: Cairo Time: 2024-04-20 20:00:00 (Africa/Cairo) Berlin Time: 2024-04-20 20:00:00 (Europe/Berlin) Event 2: Cairo Time: 2024-04-30 20:00:00 (Africa/Cairo) Berlin Time: 2024-04-30 20:00:00 (Europe/Berlin) Event 3: Cairo Time: 2024-06-05 20:00:00 (Africa/Cairo) Berlin Time: 2024-06-05 20:00:00 (Europe/Berlin) Event 4: Cairo Time: 2024-09-20 20:00:00 (Africa/Cairo) Berlin Time: 2024-09-20 20:00:00 (Europe/Berlin) Event 5: Cairo Time: 2024-10-20 20:00:00 (Africa/Cairo) Berlin Time: 2024-10-20 20:00:00 (Europe/Berlin) Event 6: Cairo Time: 2024-11-20 20:00:00 (Africa/Cairo) Berlin Time: 2024-11-20 19:00:00 (Europe/Berlin)
解决方案
1. 引入customParseFormat插件并显式指定解析格式
旧版本Chrome的Intl API时区数据不全,Day.js默认依赖该API导致DST识别错误。通过引入customParseFormat插件,显式指定日期时间格式,强制Day.js按规则解析时区:
首先安装插件:
npm install dayjs-plugin-custom-parse-format
修改代码:
import { useState, useEffect } from 'react'; import dayjs from 'dayjs'; import utc from 'dayjs/plugin/utc'; import timezone from 'dayjs/plugin/timezone'; import customParseFormat from 'dayjs/plugin/customParseFormat'; dayjs.extend(utc); dayjs.extend(timezone); dayjs.extend(customParseFormat); const defaultTimezone = "Africa/Cairo"; const dateTimeFormat = 'YYYY-MM-DDTHH:mm'; // 显式指定输入格式 // ... 其余events定义不变 function App() { const [formattedEvents, setFormattedEvents] = useState([]); useEffect(() => { const formattedEvents = events.map(event => { // 使用指定格式解析,确保时区规则生效 const cairoDateTime = dayjs.tz(`${event.date}T${event.time}`, dateTimeFormat, event.timezone); const berlinDateTime = cairoDateTime.clone().tz('Europe/Berlin'); const formattedCairoDateTime = cairoDateTime.format('YYYY-MM-DD HH:mm:ss'); const formattedBerlinDateTime = berlinDateTime.format('YYYY-MM-DD HH:mm:ss'); return { ...event, cairoDateTime: formattedCairoDateTime, berlinDateTime: formattedBerlinDateTime }; }); setFormattedEvents(formattedEvents); }, []); // ... 其余组件代码不变 } export default App;
2. 使用包含完整时区数据的Day.js构建包
Day.js的默认timezone插件依赖宿主环境的Intl API,旧浏览器的时区数据可能过时。改用包含完整IANA时区数据库的Day.js构建版本,不依赖浏览器API:
安装完整版本:
npm install dayjs-with-timezone
修改导入代码:
// 替换原有的dayjs及插件导入 import dayjs from 'dayjs-with-timezone'; // 无需单独引入utc和timezone插件,完整版本已包含 const defaultTimezone = "Africa/Cairo"; // ... 其余代码不变
3. 降级Day.js到兼容旧浏览器的稳定版本
部分新版本Day.js优化了现代浏览器支持,但牺牲了旧环境兼容性。尝试降级到v1.11.x版本(该版本对旧浏览器兼容性更好):
npm install dayjs@1.11.10
重新运行测试,验证夏令时识别是否恢复正常。
内容的提问来源于stack exchange,提问作者Sebo
相关产品推荐
相关产品推荐

