HOWTO · JavaScript
在 JavaScript 中将字符串转换为日期
本教程列出了使用 JavaScript 将字符串转换为日期的各种方法。
本页内容
数据库或 API 返回的日期值仍然是字符串,因此日期选择器或计算可能需要 JavaScript Date 对象。合适的转换方式取决于输入格式,以及字符串是否明确指定时区。将字符串作为参数传给 new Date(dateString),可解析受支持的标准格式;不带参数调用 new Date() 则会创建表示当前时间的 Date。需要毫秒数时使用 Date.parse();如果已知自定义格式,也可以自行解析各个组成部分。
本指南介绍三种实用方法:
- 将受支持的日期字符串传给
new Date(dateString),创建Date对象。 - 需要数字形式的毫秒值时,调用
Date.parse()。 - 已知自定义格式时,先拆分各个组成部分,再创建
Date。
在 JavaScript 中使用 new Date() 将字符串转换为 Date
new Date(dateString) 构造函数接受受支持的日期字符串,并返回一个 Date 对象。这个 ISO 8601 时间戳包含表示 UTC 的 Z。调用 toISOString() 会返回 UTC 时间,不受机器本地时区影响。
const dateString = '2024-05-23T14:30:00Z';
const date = new Date(dateString);
console.log(date instanceof Date);
console.log(date.toISOString());
仅包含日期的字符串(例如 2024-05-23)会被解释为 UTC;不带时区偏移量的日期时间字符串则会被解释为本地时间。如果源数据表示某个特定时刻,请使用带明确偏移量的标准格式字符串,这样解析结果就不会取决于机器的本地时区。
对于标准日期时间格式以外的字符串,JavaScript 实现之间并没有一致的解析规则。一个浏览器或运行时能够接受的字符串,在其他环境中可能会得到不同的解释。使用结果前,请通过 Number.isNaN(date.getTime()) 检查生成的对象是否有效。解析成功也不代表字符串符合应用要求的格式或日历规则;这些要求需要另外验证。
在 JavaScript 中使用 Date.parse() 解析日期字符串
Date.parse() 会将可解析的日期字符串转换为自 Unix 纪元起经过的毫秒数;无法解析时则返回 NaN。它返回的是数字,而不是 Date 对象。对于 API 返回的值,可以先解析字符串;需要对象时,再根据得到的数字创建日期:
const apiValue = '2019-01-01T12:30:00.000Z';
const milliseconds = Date.parse(apiValue);
console.log(typeof milliseconds);
console.log(Number.isNaN(milliseconds) ? 'not parsed' : new Date(milliseconds).toISOString());
Number.isNaN() 可以检测解析失败的标志,但不能完整验证应用专用的格式。运行时可能接受某个应用本应拒绝的值。如果输入必须符合特定模式,请在使用解析结果前检查该模式及其日历日期是否合法。
在 JavaScript 中拆分字符串并将其转换为 Date
如果输入采用已知的自定义格式,请按该格式拆分字符串,并将各个组成部分传给带多个参数的 Date 构造函数。此示例预期的格式为 DD-MM-YYYYTHH:mm:ss;构造函数会将这些组成部分解释为本地时间。除非它们能组成真实有效的日历日期,否则函数会返回 null。
function parseKnownDate(value) {
if (typeof value !== 'string') {
return null;
}
const dateTimeParts = value.split('T');
if (dateTimeParts.length !== 2) {
return null;
}
const [datePart, timePart] = dateTimeParts;
if (
!/^\d{2}-\d{2}-\d{4}$/.test(datePart) ||
!/^\d{2}:\d{2}:\d{2}$/.test(timePart)
) {
return null;
}
const dateParts = datePart.split('-');
const timeParts = timePart.split(':');
if (dateParts.length !== 3 || timeParts.length !== 3) {
return null;
}
const [day, month, year] = dateParts.map(Number);
const [hours, minutes, seconds] = timeParts.map(Number);
if (![day, month, year, hours, minutes, seconds].every(Number.isInteger)) {
return null;
}
// The multi-argument constructor treats years 0–99 as 1900–1999.
// setFullYear preserves the supplied year, including values in that range.
const date = new Date(0);
date.setFullYear(year, month - 1, day);
date.setHours(hours, minutes, seconds, 0);
if (
date.getFullYear() !== year ||
date.getMonth() !== month - 1 ||
date.getDate() !== day ||
date.getHours() !== hours ||
date.getMinutes() !== minutes ||
date.getSeconds() !== seconds
) {
return null;
}
return date;
}
const date = parseKnownDate('21-03-2020T11:20:30');
console.log(date === null ? 'not a valid date' : date.toString());
拆分方式取决于上述组成部分的顺序;如果源数据采用不同顺序或分隔符,就需要相应调整。月份参数从零开始计数,因此代码会将人类可读的月份减一。设置器使用本地时间,并可能将超出范围的值自动归一化;比较转换结果与解析出的组成部分,可以检测这种归一化。初始日期依据本地时区,因此此方法创建的是本地时间值,而非 UTC 时间戳。如果年份可能在 0 到 99 之间,使用 setFullYear() 可以避免多参数构造函数对这些年份的特殊处理。此示例会检查组成部分是否为整数,以及日期是否因日历进位而发生变化;如果应用的输入规则更严格,还应检查字符串是否完全符合指定模式,以及每个字段允许的取值范围。
总结
将受支持的日期字符串传给 new Date(dateString) 可创建 Date 对象;如果字符串表示某个特定时刻,最好使用带明确偏移量的格式。不带参数调用 new Date() 会创建表示当前时间的 Date,它不会解析字符串。需要自 Unix 纪元起的毫秒数,或需要用 NaN 表示解析失败时,使用 Date.parse();解析成功后,如果需要 Date 对象,可将结果传给 new Date(milliseconds)。对于已知的自定义格式,应先解析并验证各个组成部分,再创建本地时间日期。ISO 8601 概述介绍了许多 API 使用的日期和时间表示法。