JavaScript Date对象跨浏览器差异:Safari UTC日期解析异常求助
解决Safari中JavaScript Date解析无时区ISO字符串的差异问题
你碰到的这个问题真的挺头疼的——当你解析像"2018-01-01T00:00:00"这种不带时区信息的ISO格式日期字符串时,Chrome、Edge和Firefox会默认把它当作本地时区的日期处理,但Safari却会把它当成UTC时区来解析,直接导致结果差了好几个小时,甚至跨天。
不用moment.js这类第三方库的话,有几个纯原生JavaScript的方案能完美解决这个问题:
方案1:拆分日期字符串,用Date构造函数的参数模式
这是最稳妥的方法,因为当你直接把年、月、日等数值传给Date构造函数时,所有浏览器都会统一按本地时区来创建日期对象。
代码示例:
const dateString = "2018-01-01T00:00:00"; // 拆分字符串提取各个时间部分 const [year, month, day, hour, minute, second] = dateString.split(/[-T:]/); // 注意:Date的月份参数是从0开始的(1月对应0,12月对应11) const date = new Date( parseInt(year, 10), parseInt(month, 10) - 1, parseInt(day, 10), parseInt(hour, 10) || 0, parseInt(minute, 10) || 0, parseInt(second, 10) || 0 ); console.log(date); // Safari中会输出Mon Jan 01 2018 00:00:00 GMT-0800 (PST)
方案2:给日期字符串添加本地时区偏移
如果你不想拆分字符串,可以手动给原字符串加上当前本地时区的偏移标记,让Safari明确知道要按本地时区解析。
代码示例:
const dateString = "2018-01-01T00:00:00"; // 获取本地时区与UTC的偏移量(单位:分钟) const timezoneOffset = new Date().getTimezoneOffset(); // 把偏移量格式化为±HH:mm的形式 const offsetSign = timezoneOffset > 0 ? "-" : "+"; const offsetHours = Math.floor(Math.abs(timezoneOffset) / 60).toString().padStart(2, '0'); const offsetMinutes = (Math.abs(timezoneOffset) % 60).toString().padStart(2, '0'); const timezoneStr = `${offsetSign}${offsetHours}:${offsetMinutes}`; // 拼接成带时区的完整日期字符串 const localDateStr = `${dateString}${timezoneStr}`; const date = new Date(localDateStr); console.log(date); // Safari中会正确解析为本地时区的2018-01-01
方案3:手动调整UTC时间戳到本地时间
先把原字符串当作UTC解析得到时间戳,再手动加上本地时区的偏移量,转换成本地时间的时间戳后创建Date对象:
const dateString = "2018-01-01T00:00:00"; // 按UTC解析获取时间戳 const utcTimestamp = Date.parse(`${dateString}Z`); // 把时区偏移量转换成毫秒 const offsetMs = new Date().getTimezoneOffset() * 60 * 1000; // 调整成本地时间的时间戳 const localTimestamp = utcTimestamp - offsetMs; const date = new Date(localTimestamp); console.log(date); // 在Safari中同样能得到正确的本地日期
这几个方案都是纯原生JS实现,完全不需要依赖任何第三方库,都能让Safari把目标字符串解析成2018年1月1日的本地时间。
内容的提问来源于stack exchange,提问作者markreyes
相关产品推荐
相关产品推荐

