JS比较日期忽略时区 正确将UTC时间转换为Unix时间戳
问题原因
不带任何时区后缀的ISO格式时间字符串(比如你给出的"2022-07-07T11:05:53.209")传入new Date()构造函数时,JS引擎会默认按照运行环境的本地时区解析该字符串。你所在的GMT+1时区环境下,解析结果会比真实UTC时间偏移1小时,后续哪怕调用getUTC*系列方法取值,拿到的也是已经偏移后的错误时间分量,最终计算的时间差自然存在固定1小时误差。
解决方案
最简实现(推荐)
直接给原始UTC时间字符串尾部追加UTC时区标识Z,显式告知JS引擎该字符串为UTC时间,解析后直接调用getTime()就能拿到无偏移的Unix毫秒时间戳,可直接和Date.now()的结果做对比:
const nowDateTime = Date.now(); // 追加Z标识标记为UTC时间,避免引擎按本地时区解析 const lastMessageUnixEpoch = new Date(`${lastMessageTimestamp}Z`).getTime(); const difference = (nowDateTime - lastMessageUnixEpoch) / 1000;
兼容实现(无解析规则依赖)
如果需要完全规避JS引擎对日期字符串的默认解析逻辑,也可以手动按固定格式拆分时间字符串的各分量,直接传入Date.UTC生成时间戳。注意Date.UTC的月份参数从0开始计数,拆分出的月份值需要减1:
const nowDateTime = Date.now(); // 拆分日期、时间段 const [dateSection, timeSection] = lastMessageTimestamp.split('T'); const [year, month, day] = dateSection.split('-').map(Number); const [hour, minute, secondWithMs] = timeSection.split(':'); const [second, millisecond] = secondWithMs.split('.').map(Number); // 直接传入UTC时间分量生成时间戳,全程不涉及本地时区转换 const lastMessageUnixEpoch = Date.UTC( year, month - 1, // 月份从0开始计数,需减1 day, hour, minute, second, millisecond ); const difference = (nowDateTime - lastMessageUnixEpoch) / 1000;
两种实现得到的时间差结果完全一致:追加Z的写法代码简洁、可读性强;手动拆分的写法不依赖引擎的日期字符串解析规则,适配所有运行环境。
内容的提问来源于stack exchange,提问作者Mike Rifgin
相关产品推荐
相关产品推荐

