React/TypeScript中如何将无Z标识的UTC时间字符串解析为Date对象
如何将无UTC标识的时间字符串当作UTC解析(React/TypeScript)
问题背景
从REST API获取的时间字符串为2022-01-31T14:00:00,该字符串实际表示UTC时间,但末尾没有标准的Z标识。直接用new Date()解析时,会被浏览器识别为本地时区时间,导致显示结果不符合预期:
- 在GMT+10时区环境下,期望解析后显示为
Tuesday, March 1st, 2022 at 12:00:00 AM GMT+10:00 - 实际得到的却是
Monday, January 31st, 2022 at 2:00:00 PM GMT+10:00
原代码
import { format } from "date-fns"; const tsCreatedDate = new Date(2022, 2, 1) console.log("Starting Date: ", format(tsCreatedDate, 'PPPPpppp')) const tsCreatedDateStr = tsCreatedDate.toISOString() const dateStrFromApi: string = "2022-01-31T14:00:00" const parsedApiDate = new Date(dateStrFromApi) const parsedTsDate = new Date(tsCreatedDateStr) console.log("Typescript Direct: ", tsCreatedDateStr, " => ", format(parsedTsDate , 'PPPPpppp')) console.log("WEB API Date Str : ", dateStrFromApi , " => ", format(parsedApiDate, 'PPPPpppp'))
原控制台输出
Starting Date: Tuesday, March 1st, 2022 at 12:00:00 AM GMT+10:00 Typescript Direct: 2022-02-28T14:00:00.000Z => Tuesday, March 1st, 2022 at 12:00:00 AM GMT+10:00 WEB API Date Str : 2022-01-31T14:00:00 => Monday, January 31st, 2022 at 2:00:00 PM GMT+10:00
解决方案
以下三种方法均可实现将目标字符串当作UTC解析:
方法1:手动添加Z后缀(最简单)
根据ECMAScript标准,带Z后缀的ISO时间字符串会被解析为UTC时间。直接给API返回的字符串拼接Z即可:
const dateStrFromApi: string = "2022-01-31T14:00:00"; // 添加Z标识,强制按UTC解析 const parsedApiDate = new Date(`${dateStrFromApi}Z`); console.log("Fixed WEB API Date: ", format(parsedApiDate, 'PPPPpppp')); // 输出:Tuesday, March 1st, 2022 at 12:00:00 AM GMT+10:00
方法2:使用date-fns的UTC解析(更严谨)
如果需要更灵活的解析控制,可以用date-fns结合date-fns-tz的方法,明确指定解析时区为UTC:
import { format, parse } from "date-fns"; import { utcToZonedTime } from "date-fns-tz"; const dateStrFromApi: string = "2022-01-31T14:00:00"; // 按UTC规则解析字符串 const utcDate = parse(dateStrFromApi, "yyyy-MM-dd'T'HH:mm:ss", new Date(), { timeZone: "UTC" }); // 转换为本地时区并格式化 const localDate = utcToZonedTime(utcDate, Intl.DateTimeFormat().resolvedOptions().timeZone); console.log("Fixed WEB API Date: ", format(localDate, 'PPPPpppp')); // 输出:Tuesday, March 1st, 2022 at 12:00:00 AM GMT+10:00
方法3:手动拆分字符串构造UTC时间
如果不想依赖第三方库,可以手动拆分时间字段,用Date.UTC构造时间戳后转成Date对象:
const dateStrFromApi: string = "2022-01-31T14:00:00"; // 拆分年、月、日、时、分、秒 const [datePart, timePart] = dateStrFromApi.split('T'); const [year, month, day] = datePart.split('-').map(Number); const [hours, minutes, seconds] = timePart.split(':').map(Number); // Date.UTC返回UTC时间的时间戳,注意月份是0-based(0=1月) const parsedApiDate = new Date(Date.UTC(year, month - 1, day, hours, minutes, seconds)); console.log("Fixed WEB API Date: ", format(parsedApiDate, 'PPPPpppp')); // 输出:Tuesday, March 1st, 2022 at 12:00:00 AM GMT+10:00
关键原理
- ECMAScript规定:不带时区标识的
YYYY-MM-DDTHH:mm:ss格式字符串,默认按本地时区解析;带Z后缀则按UTC时区解析。 - 上述方法本质都是让解析器明确知道要按UTC规则处理输入字符串,避免本地时区的干扰。
内容的提问来源于stack exchange,提问作者Greg
相关产品推荐
相关产品推荐

