Date
Baseline 广泛可用 *
JavaScript Date 对象以平台无关的格式表示时间中的某个特定瞬间。Date 对象封装了一个整数,该整数表示自 1970 年 1 月 1 日午夜(UTC)(即**“纪元”**)以来经过的毫秒数。
描述
纪元、时间戳和无效日期
JavaScript 日期从根本上讲是自纪元以来经过的毫秒数,纪元定义为 1970 年 1 月 1 日午夜(UTC)(等同于 UNIX 纪元)。这个时间戳**与时区无关**,唯一地定义了历史上的一个瞬间。
注意: 尽管 Date 对象核心的时间值是 UTC 时间,但获取日期和时间或其组成部分的基本方法都在本地(即主机系统)时区和偏移量中运行。
Date 对象可表示的最大时间戳略小于最大安全整数(Number.MAX_SAFE_INTEGER,即 9,007,199,254,740,991)。Date 对象相对于纪元最大可表示 ±8,640,000,000,000,000 毫秒,即 ±100,000,000(一亿)天。这范围从公元前 271821 年 4 月 20 日到公元 275760 年 9 月 13 日。任何试图表示此范围之外时间的尝试都会导致 Date 对象持有 NaN 的时间戳值,即“无效日期”。
console.log(new Date(8.64e15).toString()); // "Sat Sep 13 275760 00:00:00 GMT+0000 (Coordinated Universal Time)"
console.log(new Date(8.64e15 + 1).toString()); // "Invalid Date"
有各种方法允许你与日期中存储的时间戳进行交互
- 你可以使用
getTime()和setTime()方法直接与时间戳值进行交互。 valueOf()和[Symbol.toPrimitive]()(当传入"number"时)方法——它们在数字强制转换中会自动调用——返回时间戳,使得Date对象在数字上下文中使用时表现得像它们的时间戳。- 所有静态方法(
Date.now()、Date.parse()和Date.UTC())都返回时间戳而不是Date对象。 Date()构造函数可以只用一个时间戳作为参数进行调用。
日期组成部分和时区
日期在内部表示为单个数字,即**时间戳**。与它交互时,时间戳需要被解释为结构化的日期和时间表示。解释时间戳始终有两种方式:作为本地时间或作为协调世界时(UTC),这是由世界时间标准定义的全球标准时间。本地时区不存储在日期对象中,而是由主机环境(用户设备)决定。
注意: UTC 不应与 格林威治平均时间(GMT)混淆,因为它们并非总是相等——这在链接的维基百科页面中有更详细的解释。
例如,时间戳 0 表示历史上的一个独特瞬间,但它可以有两种解释方式
- 作为 UTC 时间,它是 1970 年 1 月 1 日午夜(UTC),
- 作为纽约(UTC-5)的本地时间,它是 1969 年 12 月 31 日 19:00:00。
getTimezoneOffset() 方法返回 UTC 与本地时间之间的分钟差。请注意,时区偏移量不仅取决于当前时区,还取决于 Date 对象所表示的时间,因为存在夏令时和历史变化。本质上,时区偏移量是 Date 对象所表示的时间和主机环境所在位置与 UTC 时间的偏移量。
Date 方法分为两组:一组通过将时间戳解释为本地时间来获取和设置各种日期组件,而另一组则使用 UTC。
Date() 构造函数可以传入两个或更多参数,这种情况下它们分别被解释为本地时间中的年、月、日、小时、分钟、秒和毫秒。Date.UTC() 的工作方式类似,但它将这些组件解释为 UTC 时间,并且也接受一个表示年份的单个参数。
注意: 包括 Date() 构造函数、Date.UTC() 和已弃用的 getYear()/setYear() 方法在内的一些方法,会将两位数年份解释为 20 世纪的年份。例如,new Date(99, 5, 24) 被解释为 1999 年 6 月 24 日,而不是 99 年 6 月 24 日。有关更多信息,请参阅两位数年份的解释。
当某个片段溢出或欠流其预期范围时,它通常会“结转到”或“借用自”更高的片段。例如,如果月份设置为 12(月份从零开始,所以 12 月是 11),它将成为下一年的 1 月。如果日份设置为 0,它将成为上一个月的最后一天。这同样适用于使用日期时间字符串格式指定的日期。
当尝试将本地时间设置为落在偏移量转换期间(通常是夏令时)的时间时,确切的时间将使用与 Temporal 的 disambiguation: "compatible" 选项相同的行为推导。也就是说,如果本地时间对应两个瞬间,则选择较早的一个;如果本地时间不存在(存在间隙),则按间隙持续时间向前推移。
// Assume America/New_York local time zone
// 2024-03-10 02:30 is within the spring-forward transition and does not exist
// 01:59 (UTC-5) jumps to 03:00 (UTC-4), so 02:30 moves forward by one hour
console.log(new Date(2024, 2, 10, 2, 30).toString());
// Sun Mar 10 2024 03:30:00 GMT-0400 (Eastern Daylight Time)
// 2024-11-03 01:30 is within the fall-back transition and exists twice
// 01:59 (UTC-4) jumps to 01:00 (UTC-5), so the earlier 01:30 (UTC-4) is chosen
console.log(new Date(2024, 10, 3, 1, 30).toString());
// Sun Nov 03 2024 01:30:00 GMT-0400 (Eastern Daylight Time)
日期时间字符串格式
将日期格式化为字符串有多种方式。JavaScript 规范只指定了一种 universally supported 的格式:日期时间字符串格式,它是 ISO 8601 日历日期扩展格式的简化。格式如下:
YYYY-MM-DDTHH:mm:ss.sssZ
YYYY是年份,四位数字(0000到9999),或带有+或-后跟六位数字的扩展年份。扩展年份必须带符号。明确禁止使用-000000作为有效年份。MM是月份,两位数字(01到12)。默认为01。DD是月份中的日期,两位数字(01到31)。默认为01。T是一个字面字符,表示字符串中**时间**部分的开始。指定时间部分时,T是必需的。HH是小时,两位数字(00到23)。作为特例,允许使用24:00:00,并将其解释为下一天的午夜。默认为00。mm是分钟,两位数字(00到59)。默认为00。ss是秒,两位数字(00到59)。默认为00。sss是毫秒,三位数字(000到999)。默认为000。Z是时区偏移量,可以是字面字符Z(表示 UTC),也可以是+或-后跟HH:mm,即与 UTC 的小时和分钟偏移量。
各种组件可以省略,因此以下所有格式都是有效的
- 仅日期形式:
YYYY、YYYY-MM、YYYY-MM-DD - 日期时间形式:上述仅日期形式之一,后跟
T,再后跟HH:mm、HH:mm:ss或HH:mm:ss.sss。每种组合都可以后跟时区偏移量。
例如,"2011-10-10"(*仅日期*形式)、"2011-10-10T14:48:00"(*日期时间*形式)或 "2011-10-10T14:48:00.000+09:00"(带毫秒和时区的*日期时间*形式)都是有效的日期时间字符串。
当缺少时区偏移量时,**仅日期形式被解释为 UTC 时间,而日期时间形式被解释为本地时间。** 将其解释为 UTC 时间是由于一个与 ISO 8601 不一致的历史规范错误,但由于网络兼容性问题无法更改。请参阅 Broken Parser – A Web Reality Issue。
Date.parse() 和 Date() 构造函数都接受日期时间字符串格式的字符串作为输入。此外,当输入不匹配此格式时,实现允许支持其他日期格式。
toISOString() 方法以日期时间字符串格式返回日期的字符串表示,时区偏移量始终设置为 Z (UTC)。
注意: 建议您确保输入符合上述日期时间字符串格式,以实现最大兼容性,因为不保证支持其他格式。但是,有些格式在所有主要实现中都受支持——例如 RFC 2822 格式——在这种情况下,它们的使用可能是可以接受的。始终进行跨浏览器测试以确保您的代码在所有目标浏览器中都能正常工作。如果需要适应许多不同的格式,可以使用库来提供帮助。
非标准字符串可以按照实现所需的方式进行解析,包括时区——大多数实现默认使用本地时区。实现不要求对超出范围的日期组件返回无效日期,尽管它们通常会这样做。字符串可能包含在范围内的日期组件(其范围如上所述),但实际上并不表示日期(例如,“2 月 30 日”)。在这种情况下,实现的行为不一致。Date.parse() 页面提供了更多关于这些非标准情况的示例。
其他日期格式化方式
toISOString()返回1970-01-01T00:00:00.000Z格式的字符串(上面介绍的日期时间字符串格式,它是简化的 ISO 8601)。toJSON()调用toISOString()并返回结果。toString()返回Thu Jan 01 1970 00:00:00 GMT+0000 (Coordinated Universal Time)格式的字符串,而toDateString()和toTimeString()分别返回字符串的日期和时间部分。[Symbol.toPrimitive]()(当传入"string"或"default"时)调用toString()并返回结果。toUTCString()返回Thu, 01 Jan 1970 00:00:00 GMT格式的字符串(通用 RFC 7231)。toLocaleDateString()、toLocaleTimeString()和toLocaleString()使用特定于语言环境的日期和时间格式,通常由IntlAPI 提供。
有关示例,请参阅toString 方法返回值格式部分。
构造函数
Date()-
作为构造函数调用时,返回一个新的
Date对象。作为函数调用时,返回当前日期和时间的字符串表示。
静态方法
Date.now()-
返回对应当前时间的数值——自 1970 年 1 月 1 日 00:00:00 UTC 以来的毫秒数,忽略闰秒。
Date.parse()-
解析日期的字符串表示,并返回自 1970 年 1 月 1 日 00:00:00 UTC 以来的毫秒数,忽略闰秒。
Date.UTC()-
接受与构造函数最长形式相同的参数(即 2 到 7 个),并返回自 1970 年 1 月 1 日 00:00:00 UTC 以来的毫秒数,忽略闰秒。
实例属性
这些属性在 Date.prototype 上定义,并由所有 Date 实例共享。
Date.prototype.constructor-
创建实例对象的构造函数。对于
Date实例,初始值是Date构造函数。
实例方法
Date.prototype.getDate()-
根据本地时间返回指定日期的月份中的日期(
1–31)。 Date.prototype.getDay()-
根据本地时间返回指定日期的星期几(
0–6)。 Date.prototype.getFullYear()-
根据本地时间返回指定日期的年份(四位年份为 4 位数字)。
Date.prototype.getHours()-
根据本地时间返回指定日期中的小时(
0–23)。 Date.prototype.getMilliseconds()-
根据本地时间返回指定日期中的毫秒(
0–999)。 Date.prototype.getMinutes()-
根据本地时间返回指定日期中的分钟(
0–59)。 Date.prototype.getMonth()-
根据本地时间返回指定日期中的月份(
0–11)。 Date.prototype.getSeconds()-
根据本地时间返回指定日期中的秒数(
0–59)。 Date.prototype.getTime()-
返回指定日期的数值,即自 1970 年 1 月 1 日 00:00:00 UTC 以来的毫秒数。(对于之前的时间返回负值。)
Date.prototype.getTimezoneOffset()-
返回当前语言环境的时区偏移量(以分钟为单位)。
Date.prototype.getUTCDate()-
根据通用时间返回指定日期中月份的日期(
1–31)。 Date.prototype.getUTCDay()-
根据通用时间返回指定日期中星期几(
0–6)。 Date.prototype.getUTCFullYear()-
根据通用时间返回指定日期中的年份(四位年份为 4 位数字)。
Date.prototype.getUTCHours()-
根据通用时间返回指定日期中的小时(
0–23)。 Date.prototype.getUTCMilliseconds()-
根据通用时间返回指定日期中的毫秒(
0–999)。 Date.prototype.getUTCMinutes()-
根据通用时间返回指定日期中的分钟(
0–59)。 Date.prototype.getUTCMonth()-
根据通用时间返回指定日期中的月份(
0–11)。 Date.prototype.getUTCSeconds()-
根据通用时间返回指定日期中的秒数(
0–59)。 Date.prototype.getYear()已弃用-
根据本地时间返回指定日期中的年份(通常为 2-3 位数字)。请改用
getFullYear()。 Date.prototype.setDate()-
根据本地时间设置指定日期的月份中的日期。
Date.prototype.setFullYear()-
根据本地时间设置指定日期的完整年份(例如,四位年份为 4 位数字)。
Date.prototype.setHours()-
根据本地时间设置指定日期的小时。
Date.prototype.setMilliseconds()-
根据本地时间设置指定日期的毫秒。
Date.prototype.setMinutes()-
根据本地时间设置指定日期的分钟。
Date.prototype.setMonth()-
根据本地时间设置指定日期的月份。
Date.prototype.setSeconds()-
根据本地时间设置指定日期的秒数。
Date.prototype.setTime()-
将
Date对象设置为自 1970 年 1 月 1 日 00:00:00 UTC 以来的毫秒数所表示的时间。对于之前的时间使用负数。 Date.prototype.setUTCDate()-
根据通用时间设置指定日期的月份中的日期。
Date.prototype.setUTCFullYear()-
根据通用时间设置指定日期的完整年份(例如,四位年份为 4 位数字)。
Date.prototype.setUTCHours()-
根据通用时间设置指定日期的小时。
Date.prototype.setUTCMilliseconds()-
根据通用时间设置指定日期的毫秒。
Date.prototype.setUTCMinutes()-
根据通用时间设置指定日期的分钟。
Date.prototype.setUTCMonth()-
根据通用时间设置指定日期的月份。
Date.prototype.setUTCSeconds()-
根据通用时间设置指定日期的秒数。
Date.prototype.setYear()已弃用-
根据本地时间设置指定日期的年份(通常为 2-3 位数字)。请改用
setFullYear()。 Date.prototype.toDateString()-
以人类可读的字符串形式返回
Date的“日期”部分,例如'Thu Apr 12 2018'。 Date.prototype.toISOString()-
将日期转换为遵循 ISO 8601 扩展格式的字符串。
Date.prototype.toJSON()-
使用
toISOString()返回表示Date的字符串。旨在被JSON.stringify()隐式调用。 Date.prototype.toLocaleDateString()-
根据系统设置,返回此日期的日期部分,以语言环境敏感的字符串表示。
Date.prototype.toLocaleString()-
返回此日期的语言环境敏感表示的字符串。覆盖
Object.prototype.toLocaleString()方法。 Date.prototype.toLocaleTimeString()-
根据系统设置,返回此日期的时间部分,以语言环境敏感的字符串表示。
Date.prototype.toString()-
返回表示指定
Date对象的字符串。覆盖Object.prototype.toString()方法。 Date.prototype.toTemporalInstant()实验性-
返回一个新的
Temporal.Instant对象,其epochMilliseconds值与此日期的时间戳相同。 Date.prototype.toTimeString()-
以人类可读的字符串形式返回
Date的“时间”部分。 Date.prototype.toUTCString()-
使用 UTC 时区将日期转换为字符串。
Date.prototype.valueOf()-
返回
Date对象的原始值。覆盖Object.prototype.valueOf()方法。 Date.prototype[Symbol.toPrimitive]()-
将此
Date对象转换为原始值。
示例
创建 Date 对象的几种方式
以下示例展示了创建 JavaScript 日期的几种方式
注意: 从字符串创建日期存在许多行为不一致之处。有关使用不同格式的注意事项,请参阅日期时间字符串格式。
const today = new Date();
const birthday = new Date("December 17, 1995 03:24:00"); // DISCOURAGED: may not work in all runtimes
const birthday2 = new Date("1995-12-17T03:24:00"); // This is standardized and will work reliably
const birthday3 = new Date(1995, 11, 17); // the month is 0-indexed
const birthday4 = new Date(1995, 11, 17, 3, 24, 0);
const birthday5 = new Date(628021800000); // passing epoch timestamp
toString 方法返回值的格式
const date = new Date("2020-05-12T23:50:21.817Z");
date.toString(); // Tue May 12 2020 18:50:21 GMT-0500 (Central Daylight Time)
date.toDateString(); // Tue May 12 2020
date.toTimeString(); // 18:50:21 GMT-0500 (Central Daylight Time)
date[Symbol.toPrimitive]("string"); // Tue May 12 2020 18:50:21 GMT-0500 (Central Daylight Time)
date.toISOString(); // 2020-05-12T23:50:21.817Z
date.toJSON(); // 2020-05-12T23:50:21.817Z
date.toUTCString(); // Tue, 12 May 2020 23:50:21 GMT
date.toLocaleString(); // 5/12/2020, 6:50:21 PM
date.toLocaleDateString(); // 5/12/2020
date.toLocaleTimeString(); // 6:50:21 PM
获取日期、月份和年份或时间
const date = new Date("2000-01-17T16:45:30");
const [month, day, year] = [
date.getMonth(),
date.getDate(),
date.getFullYear(),
];
// [0, 17, 2000] as month are 0-indexed
const [hour, minutes, seconds] = [
date.getHours(),
date.getMinutes(),
date.getSeconds(),
];
// [16, 45, 30]
两位数年份的解释
new Date() 在处理两位数年份值时表现出遗留的、不一致的不良行为;具体来说,当 new Date() 调用给定两位数年份值时,该年份值不会被视为字面年份并按原样使用,而是被解释为相对偏移量——在某些情况下是相对于 1900 年的偏移量,但在其他情况下是相对于 2000 年的偏移量。
let date = new Date(98, 1); // Sun Feb 01 1998 00:00:00 GMT+0000 (GMT)
date = new Date(22, 1); // Wed Feb 01 1922 00:00:00 GMT+0000 (GMT)
date = new Date("2/1/22"); // Tue Feb 01 2022 00:00:00 GMT+0000 (GMT)
// Legacy method; always interprets two-digit year values as relative to 1900
date.setYear(98);
date.toString(); // Sun Feb 01 1998 00:00:00 GMT+0000 (GMT)
date.setYear(22);
date.toString(); // Wed Feb 01 1922 00:00:00 GMT+0000 (GMT)
因此,要创建和获取 0 到 99 年之间的日期,请改用首选的 setFullYear() 和 getFullYear() 方法:。
// Preferred method; never interprets any value as being a relative offset,
// but instead uses the year value as-is
date.setFullYear(98);
date.getFullYear(); // 98 (not 1998)
date.setFullYear(22);
date.getFullYear(); // 22 (not 1922, not 2022)
计算经过的时间
以下示例展示了如何确定两个 JavaScript 日期之间经过的毫秒数。
由于天(因夏令时变更)、月和年的长度不同,以小时、分钟和秒以外的单位表示经过时间需要解决许多问题,在尝试之前应进行彻底研究。
// Using Date objects
const start = Date.now();
// The event to time goes here:
doSomethingForALongTime();
const end = Date.now();
const elapsed = end - start; // elapsed time in milliseconds
// Using built-in methods
const start = new Date();
// The event to time goes here:
doSomethingForALongTime();
const end = new Date();
const elapsed = end.getTime() - start.getTime(); // elapsed time in milliseconds
// To test a function and get back its return
function printElapsedTime(testFn) {
const startTime = Date.now();
const result = testFn();
const endTime = Date.now();
console.log(`Elapsed time: ${String(endTime - startTime)} milliseconds`);
return result;
}
const yourFunctionReturn = printElapsedTime(yourFunction);
注意: 在支持 性能 API 高分辨率时间功能的浏览器中,Performance.now() 可以提供比 Date.now() 更可靠和精确的经过时间测量。
获取自 ECMAScript 纪元以来的秒数
const seconds = Math.floor(Date.now() / 1000);
在这种情况下,重要的是只返回一个整数——所以简单的除法不行。同样重要的是只返回实际经过的秒数。(这就是为什么这段代码使用 Math.floor(),而**不是** Math.round()。)
规范
| 规范 |
|---|
| ECMAScript® 2026 语言规范 # sec-date-objects |
浏览器兼容性
加载中…