日期

JavaScript Date 对象以独立于平台的格式表示单个时刻。Date 对象封装一个整数,表示自 UTC(纪元)1970 年 1 月 1 日午夜开始以来的毫秒数。

¥JavaScript Date objects represent a single moment in time in a platform-independent format. Date objects encapsulate an integral number that represents milliseconds since the midnight at the beginning of January 1, 1970, UTC (the epoch).

注意:TC39 正在开发 ,一个新的日期/时间 API。在 伊加利亚博客 上了解更多相关信息。它尚未准备好用于生产使用!

¥Note: TC39 is working on Temporal, a new Date/Time API. Read more about it on the Igalia blog. It is not yet ready for production use!

描述

¥Description

纪元、时间戳和无效日期

¥The epoch, timestamps, and invalid date

JavaScript 日期基本上被指定为自 epoch 以来经过的时间(以毫秒为单位),epoch 定义为 UTC 1970 年 1 月 1 日开始的午夜(相当于 UNIX 时代)。该时间戳与时区无关,并且唯一地定义了历史上的某个时刻。

¥A JavaScript date is fundamentally specified as the time in milliseconds that has elapsed since the epoch, which is defined as the midnight at the beginning of January 1, 1970, UTC (equivalent to the UNIX epoch). This timestamp is timezone-agnostic and uniquely defines an instant in history.

注意:虽然 Date 对象的核心时间值是 UTC,但获取日期和时间或其组件的基本方法都在本地(即主机系统)时区和偏移量中工作。

¥Note: While the time value at the heart of a Date object is UTC, the basic methods to fetch the date and time or its components all work in the local (i.e. host system) time zone and offset.

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,即 "失效日期"。

¥The maximum timestamp representable by a Date object is slightly smaller than the maximum safe integer (Number.MAX_SAFE_INTEGER, which is 9,007,199,254,740,991). A Date object can represent a maximum of ±8,640,000,000,000,000 milliseconds, or ±100,000,000 (one hundred million) days, relative to the epoch. This is the range from April 20, 271821 BC to September 13, 275760 AD. Any attempt to represent a time outside this range results in the Date object holding a timestamp value of NaN, which is an "Invalid Date".

js
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"

有多种方法允许你与日期中存储的时间戳进行交互:

¥There are various methods that allow you to interact with the timestamp stored in the date:

日期组成部分和时区

¥Date components and time zones

日期在内部表示为单个数字,即时间戳。与之交互时,时间戳需要被解释为结构化的日期和时间表示。总是有两种方法来解释时间戳:作为当地时间或作为协调世界时 (UTC),即由世界时间标准定义的全球标准时间。本地时区不存储在日期对象中,而是由主机环境(用户的设备)确定。

¥A date is represented internally as a single number, the timestamp. When interacting with it, the timestamp needs to be interpreted as a structured date-and-time representation. There are always two ways to interpret a timestamp: as a local time or as a Coordinated Universal Time (UTC), the global standard time defined by the World Time Standard. The local timezone is not stored in the date object, but is determined by the host environment (user's device).

注意:UTC 不应与 格林威治标准时间 (GMT) 混淆,因为它们并不总是相等 - 这在链接的维基百科页面中有更详细的解释。

¥Note: UTC should not be confused with the Greenwich Mean Time (GMT), because they are not always equal — this is explained in more detail in the linked Wikipedia page.

例如,时间戳 0 代表历史上唯一的时刻,但它可以用两种方式解释:

¥For example, the timestamp 0 represents a unique instant in history, but it can be interpreted in two ways:

  • 作为 UTC 时间,是 1970 年 1 月 1 日开始的午夜,UTC,
  • 纽约当地时间(UTC-5)为 1969 年 12 月 31 日 19:00:00。

getTimezoneOffset() 方法返回 UTC 和本地时间之间的差异(以分钟为单位)。请注意,由于夏令时和历史变化,时区偏移不仅取决于当前时区,还取决于 Date 对象表示的时间。本质上,时区偏移量是 Date 对象表示的时间和主机环境位置相对于 UTC 时间的偏移量。

¥The getTimezoneOffset() method returns the difference between UTC and the local time in minutes. Note that the timezone offset does not only depend on the current timezone, but also on the time represented by the Date object, because of daylight saving time and historical changes. In essence, the timezone offset is the offset from UTC time, at the time represented by the Date object and at the location of the host environment.

Date 方法有两组:一组通过将时间戳解释为本地时间来获取和设置各种日期组件,而另一组则使用 UTC。

¥There are two groups of Date methods: one group gets and sets various date components by interpreting the timestamp as a local time, while the other uses UTC.

组件 当地的 UTC
得到 集合 得到 集合
getFullYear() setFullYear() getUTCFullYear() setUTCFullYear()
getMonth() setMonth() getUTCMonth() setUTCMonth()
日期(月) getDate() setDate() getUTCDate() setUTCDate()
小时 getHours() setHours() getUTCHours() setUTCHours()
分钟 getMinutes() setMinutes() getUTCMinutes() setUTCMinutes()
秒数 getSeconds() setSeconds() getUTCSeconds() setUTCSeconds()
毫秒 getMilliseconds() setMilliseconds() getUTCMilliseconds() setUTCMilliseconds()
某天(一周) getDay() N/A getUTCDay() N/A

可以使用两个或多个参数调用 Date() 构造函数,在这种情况下,它们分别被解释为当地时间的年、月、日、小时、分钟、秒和毫秒。Date.UTC() 的工作方式类似,但它将组件解释为 UTC 时间,并且还接受代表年份的单个参数。

¥The Date() constructor can be called with two or more arguments, in which case they are interpreted as the year, month, day, hour, minute, second, and millisecond, respectively, in local time. Date.UTC() works similarly, but it interprets the components as UTC time and also accepts a single argument representing the year.

注意:某些方法(包括 Date() 构造函数、Date.UTC() 和已弃用的 getYear()/setYear() 方法)将两位数年份解释为 1900 年代的年份。例如,new Date(99, 5, 24) 被解释为 1999 年 6 月 24 日,而不是 99 年 6 月 24 日。请参阅 两位数年份的解释 了解更多信息。

¥Note: Some methods, including the Date() constructor, Date.UTC(), and the deprecated getYear()/setYear() methods, interpret a two-digit year as a year in the 1900s. For example, new Date(99, 5, 24) is interpreted as June 24, 1999, not June 24, 99. See Interpretation of two-digit years for more information.

当一个段上溢或下溢其预期范围时,它通常是 "延续到" 或 "借自" 较高的段。例如,如果月份设置为 12(月份从零开始,因此 12 月为 11),则它将成为下一年的 1 月。如果月份的日期设置为 0,则它将成为上个月的最后一天。这也适用于 日期时间字符串格式 指定的日期。

¥When a segment overflows or underflows its expected range, it usually "carries over to" or "borrows from" the higher segment. For example, if the month is set to 12 (months are zero-based, so December is 11), it become the January of the next year. If the day of month is set to 0, it becomes the last day of the previous month. This also applies to dates specified with the date time string format.

日期时间字符串格式

¥Date time string format

将日期格式化为字符串的方法有很多种。JavaScript 规范只指定了一种普遍支持的格式:日期时间字符串格式,ISO 8601 日历日期扩展格式的简化。格式如下:

¥There are many ways to format a date as a string. The JavaScript specification only specifies one format to be universally supported: the date time string format, a simplification of the ISO 8601 calendar date extended format. The format is as follows:

YYYY-MM-DDTHH:mm:ss.sssZ
  • YYYY 是年份,有四位数字(00009999),或者是 +- 的扩展年份,后跟六位数字。延长年份需要该标志。明确不允许 -000000 作为有效年份。
  • MM 是月份,有两位数(0112)。默认为 01
  • DD 是月份中的第几天,有两位数(0131)。默认为 01
  • T 是一个文字字符,表示字符串时间部分的开头。指定时间部分时需要 T
  • HH 是小时,有两位数(0023)。作为特殊情况,24:00:00 是允许的,并被解释为第二天开始的午夜。默认为 00
  • mm 是分钟,有两位数(0059)。默认为 00
  • ss 是第二个,有两位数(0059)。默认为 00
  • sss 是毫秒,三位数(000999)。默认为 000
  • Z 是时区偏移量,可以是文字字符 Z(表示 UTC),也可以是 +- 后跟 HH:mm,即相对于 UTC 的小时和分钟偏移量。

各种组件都可以省略,因此以下内容都是有效的:

¥Various components can be omitted, so the following are all valid:

  • 仅日期形式:YYYY, YYYY-MM, YYYY-MM-DD
  • 日期时间形式:上述仅日期形式之一,后跟 T,后跟 HH:mmHH:mm:ssHH:mm:ss.sss。每个组合后面都可以跟一个时区偏移量。

例如,"2011-10-10"(仅日期形式)、"2011-10-10T14:48:00"(日期时间形式)或 "2011-10-10T14:48:00.000+09:00"(带有毫秒和时区的日期时间形式)都是有效的日期时间字符串。

¥For example, "2011-10-10" (date-only form), "2011-10-10T14:48:00" (date-time form), or "2011-10-10T14:48:00.000+09:00" (date-time form with milliseconds and time zone) are all valid date time strings.

当时区偏移量不存在时,仅日期形式将解释为 UTC 时间,而日期时间形式将解释为本地时间。这是由于历史规范错误导致的,该错误与 ISO 8601 不一致,但由于 Web 兼容性而无法更改。参见 损坏的解析器 – Web 现实问题

¥When the time zone offset is absent, date-only forms are interpreted as a UTC time and date-time forms are interpreted as local time. This is due to a historical spec error that was not consistent with ISO 8601 but could not be changed due to web compatibility. See Broken Parser – A Web Reality Issue.

Date.parse()Date() 构造函数都接受日期时间字符串格式的字符串作为输入。此外,当输入与此格式不匹配时,允许实现支持其他日期格式。

¥Date.parse() and the Date() constructor both accept strings in the date time string format as input. Furthermore, implementations are allowed to support other date formats when the input fails to match this format.

toISOString() 方法以日期时间字符串格式返回日期的字符串表示形式,时区偏移量始终设置为 Z (UTC)。

¥The toISOString() method returns a string representation of the date in the date time string format, with the time zone offset always set to Z (UTC).

注意:我们鼓励你确保你的输入符合上面的日期时间字符串格式以获得最大兼容性,因为不保证对其他格式的支持。然而,有些格式在所有主要实现中都受支持 - 例如 RFC 2822 格式 - 在这种情况下它们的使用是可以接受的。始终执行 跨浏览器测试 以确保你的代码可以在所有目标浏览器中运行。如果要容纳多种不同的格式,库可以提供帮助。

¥Note: You are encouraged to make sure your input conforms to the date time string format above for maximum compatibility, because support for other formats is not guaranteed. However, there are some formats that are supported in all major implementations — like RFC 2822 format — in which case their usage can be acceptable. Always conduct cross-browser tests to ensure your code works in all target browsers. A library can help if many different formats are to be accommodated.

非标准字符串可以根据实现的需要以任何方式进行解析,包括时区 - 大多数实现默认使用本地时区。实现不需要为越界日期组件返回无效日期,尽管它们通常会这样做。字符串可能具有边界内日期组件(具有上面定义的边界),但并不代表现实中的日期(例如,"2 月 30 日")。在这种情况下,实现行为不一致。Date.parse() 页面提供了有关这些非标准案例的更多示例。

¥Non-standard strings can be parsed in any way as desired by the implementation, including the time zone — most implementations use the local time zone by default. Implementations are not required to return invalid date for out-of-bounds date components, although they usually do. A string may have in-bounds date components (with the bounds defined above), but does not represent a date in reality (for example, "February 30"). Implementations behave inconsistently in this case. The Date.parse() page offers more examples about these non-standard cases.

设置日期格式的其他方法

¥Other ways to format a date

有关示例,请参阅 toString 方法返回值的格式 部分。

¥See the Formats of toString method return values section for examples.

构造函数

¥Constructor

Date()

当作为构造函数调用时,返回一个新的 Date 对象。当作为函数调用时,返回当前日期和时间的字符串表示形式。

静态方法

¥Static methods

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 以来的毫秒数,忽略闰秒。

实例属性

¥Instance properties

这些属性在 Date.prototype 上定义并由所有 Date 实例共享。

¥These properties are defined on Date.prototype and shared by all Date instances.

Date.prototype.constructor

创建实例对象的构造函数。对于 Date 实例,初始值为 Date 构造函数。

实例方法

¥Instance methods

Date.prototype.getDate()

根据当地时间返回指定日期的月份(131)。

Date.prototype.getDay()

根据当地时间返回指定日期是星期几 (06)。

Date.prototype.getFullYear()

根据当地时间返回指定日期的年份(4 位数字年份)。

Date.prototype.getHours()

根据当地时间返回指定日期的小时 (023)。

Date.prototype.getMilliseconds()

根据当地时间返回指定日期的毫秒数 (0999)。

Date.prototype.getMinutes()

根据当地时间返回指定日期的分钟 (059)。

Date.prototype.getMonth()

根据当地时间返回指定日期的月份 (011)。

Date.prototype.getSeconds()

根据当地时间返回指定日期的秒数 (059)。

Date.prototype.getTime()

以自 1970 年 1 月 1 日 00:00:00 UTC 以来的毫秒数形式返回指定日期的数值。(之前的时间返回负值。)

Date.prototype.getTimezoneOffset()

返回当前区域设置的时区偏移量(以分钟为单位)。

Date.prototype.getUTCDate()

根据世界时间返回指定日期的月份(131)中的第几天(日期)。

Date.prototype.getUTCDay()

根据通用时间返回指定日期中的星期几 (06)。

Date.prototype.getUTCFullYear()

根据通用时间返回指定日期的年份(4 位数字年份)。

Date.prototype.getUTCHours()

根据通用时间返回指定日期的小时 (023)。

Date.prototype.getUTCMilliseconds()

根据世界时间返回指定日期的毫秒数 (0999)。

Date.prototype.getUTCMinutes()

根据通用时间返回指定日期的分钟 (059)。

Date.prototype.getUTCMonth()

根据通用时间返回指定日期的月份 (011)。

Date.prototype.getUTCSeconds()

根据世界时间返回指定日期的秒数 (059)。

Date.prototype.getYear() Deprecated

根据当地时间返回指定日期的年份(通常为 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() Deprecated

根据当地时间设置指定日期的年份(通常为 2-3 位数字)。请改用 setFullYear()

Date.prototype.toDateString()

Date 的 "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.toTimeString()

以人类可读的字符串形式返回 Date 的 "time" 部分。

Date.prototype.toUTCString()

使用 UTC 时区将日期转换为字符串。

Date.prototype.valueOf()

返回 Date 对象的原始值。覆盖 Object.prototype.valueOf() 方法。

Date.prototype[Symbol.toPrimitive]()

将此 Date 对象转换为原始值。

示例

¥Examples

创建 Date 对象的几种方法

¥Several ways to create a Date object

以下示例展示了创建 JavaScript 日期的几种方法:

¥The following examples show several ways to create JavaScript dates:

注意:从字符串创建日期有很多行为不一致的地方。有关使用不同格式的注意事项,请参阅 日期时间字符串格式

¥Note: Creating a date from a string has a lot of behavior inconsistencies. See date time string format for caveats on using different formats.

js
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 方法返回值的格式

¥Formats of toString method return values

js
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

获取日期、月份和年份或时间

¥To get Date, Month and Year or Time

js
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]

两位数年份的解释

¥Interpretation of two-digit years

new Date() 表现出遗留的不良行为,与两位数的年份值不一致;具体来说,当 new Date() 调用被赋予两位数的年份值时,该年份值不会被视为文字年份并按原样使用,而是被解释为相对偏移量 - 在某些情况下解释为相对于年份 1900 的偏移量 ,但在其他情况下,作为 2000 年的偏移量。

¥new Date() exhibits legacy undesirable, inconsistent behavior with two-digit year values; specifically, when a new Date() call is given a two-digit year value, that year value does not get treated as a literal year and used as-is but instead gets interpreted as a relative offset — in some cases as an offset from the year 1900, but in other cases, as an offset from the year 2000.

js
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)

因此,要创建和获取 099 之间的日期,请使用首选的 setFullYear()getFullYear() 方法:

¥So, to create and get dates between the years 0 and 99, instead use the preferred setFullYear() and getFullYear() methods:.

js
// 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)

计算经过的时间

¥Calculating elapsed time

以下示例演示如何确定两个 JavaScript 日期之间经过的时间(以毫秒为单位)。

¥The following examples show how to determine the elapsed time between two JavaScript dates in milliseconds.

由于日(由于夏令时转换)、月和年的长度不同,以大于小时、分钟和秒的单位表示经过的时间需要解决许多问题,并且在尝试之前应进行彻底研究。

¥Due to the differing lengths of days (due to daylight saving changeover), months, and years, expressing elapsed time in units greater than hours, minutes, and seconds requires addressing a number of issues, and should be thoroughly researched before being attempted.

js
// 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
js
// 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
js
// 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);

注意:在支持 Performance API 高分辨率时间功能的浏览器中,Performance.now() 可以提供比 Date.now() 更可靠、更精确的经过时间测量。

¥Note: In browsers that support the Performance API's high-resolution time feature, Performance.now() can provide more reliable and precise measurements of elapsed time than Date.now().

获取自 ECMAScript Epoch 以来的秒数

¥Get the number of seconds since the ECMAScript Epoch

js
const seconds = Math.floor(Date.now() / 1000);

在这种情况下,仅返回一个整数非常重要,因此简单的除法是行不通的。仅返回实际经过的秒数也很重要。(这就是为什么此代码使用 Math.floor(),而不是 Math.round()。)

¥In this case, it's important to return only an integer—so a simple division won't do. It's also important to only return actually elapsed seconds. (That's why this code uses Math.floor(), and not Math.round().)

规范

Specification
ECMAScript Language Specification
# sec-date-objects

¥Specifications

浏览器兼容性

BCD tables only load in the browser

¥Browser compatibility

也可以看看

¥See also