/

JavaScript 日期的完全指南

JavaScript 日期的完全指南

在JavaScript中使用日期可能很复杂。学习所有的技巧以及如何使用它们。

处理日期可以很“复杂”。无论使用什么技术,开发人员都会感到痛苦。

JavaScript提供了一个通过强大的内置对象Date来处理日期的功能。

提示:当处理日期时,您可能希望使用一个库。Moment.jsdate-fns是最流行的两个。

日期对象

一个日期对象实例表示一个时间点。

尽管名字是Date,它也处理时间

初始化日期对象

我们使用以下方式初始化一个日期对象。

1
new Date()

这将创建一个指向当前时间点的日期对象。

在内部,日期以从1970年1月1日(UTC)以来的毫秒表示。这个日期很重要,因为在计算机看来,一切都是在那一天开始的。

您可能对UNIX时间戳很熟悉:它代表了自那个著名日期以来经过的秒数

如果我们有一个UNIX时间戳,我们可以使用以下方式实例化一个JavaScript日期对象:

1
2
const timestamp = 1530826365;
new Date(timestamp * 1000);

除非时间戳是由JS生成的,否则它已经在正确的比例上。

确保传递一个数字(字符串将得到一个“无效的日期”结果 - 如有疑问请使用parseInt()

如果我们传递0,我们将得到一个代表1970年1月1日(UTC)时间的日期对象:

1
new Date(0)

如果我们传递一个字符串而不是数字,那么日期对象将使用parse方法来确定您传递的日期。例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
new Date('2018-07-22')
new Date('2018-07') // 2018年7月1日,00:00:00
new Date('2018') // 2018年1月1日,00:00:00
new Date('07/22/2018')
new Date('2018/07/22')
new Date('2018/7/22')
new Date('July 22, 2018')
new Date('July 22, 2018 07:22:13')
new Date('2018-07-22 07:22:13')
new Date('2018-07-22T07:22:13')
new Date('25 March 2018')
new Date('25 Mar 2018')
new Date('25 March, 2018')
new Date('March 25, 2018')
new Date('March 25 2018')
new Date('March 2018') // 2018年3月1日,00:00:00
new Date('2018 March') // 2018年3月1日,00:00:00
new Date('2018 MARCH') // 2018年3月1日,00:00:00
new Date('2018 march') // 2018年3月1日,00:00:00

这里有很大的灵活性。您可以在月份或日期中添加或省略前导零。

注意月份/日期的位置,否则可能导致将月份误解为日期。

您也可以使用Date.parse

1
2
3
4
5
6
7
8
9
10
Date.parse('2018-07-22')
Date.parse('2018-07') // 2018年7月1日,00:00:00
Date.parse('2018') // 2018年1月1日,00:00:00
Date.parse('07/22/2018')
Date.parse('2018/07/22')
Date.parse('2018/7/22')
Date.parse('July 22, 2018')
Date.parse('July 22, 2018 07:22:13')
Date.parse('2018-07-22 07:22:13')
Date.parse('2018-07-22T07:22:13')

Date.parse将返回一个时间戳(以毫秒为单位),而不是一个日期对象。

您也可以传递一组有序的值,表示日期的每个部分:年份,月份(从0开始),日期,小时,分钟,秒和毫秒:

1
2
new Date(2018, 6, 22, 7, 22, 13, 0)
new Date(2018, 6, 22)

最少应该有3个参数,但大多数JavaScript引擎也会处理比这些参数更少的情况:

1
2
new Date(2018, 6) // 2018年7月1日,00:00:00 GMT+0200(中央欧洲夏令时)
new Date(2018) // 1970年1月1日星期四,01:00:02 GMT+0100(中欧标准时间)

在上述任何情况下,所得到的日期都相对于计算机的时区。这意味着两台不同的计算机可能会为相同的日期对象输出不同的值

JavaScript在没有关于时区的任何信息的情况下,会将日期视为UTC,并自动将其转换为当前计算机时区。

所以,总结一下,您可以通过以下4种方式创建一个新的日期对象

  • 不传递任何参数,创建一个表示“现在”的日期对象
  • 传递一个数字,它表示从1970年1月1日00:00 GMT开始的毫秒数
  • 传递一个字符串,它表示一个日期
  • 传递一组参数,它们表示日期的不同部分

时区

当初始化日期时,您可以通过添加+HOURS格式的时区或将时区名称添加到括号中来指定时区:

1
2
new Date('July 22, 2018 07:22:13 +0700')
new Date('July 22, 2018 07:22:13 (CET)')

如果您在括号中指定了错误的时区名称,JavaScript将默认为UTC,而不会报错。

如果您指定了错误的数字格式,JavaScript将给出“Invalid Date”错误。

日期转换和格式化

给定一个日期对象,有许多方法可以从该日期生成一个字符串:

1
2
3
4
5
6
7
8
9
10
11
const date = new Date('July 22, 2018 07:22:13')

date.toString() // "Sun Jul 22 2018 07:22:13 GMT+0200 (中央欧洲夏时制)"
date.toTimeString() //"07:22:13 GMT+0200 (中央欧洲夏时制)"
date.toUTCString() //"Sun, 22 Jul 2018 05:22:13 GMT"
date.toDateString() //"Sun Jul 22 2018"
date.toISOString() //"2018-07-22T05:22:13.000Z"(ISO 8601格式)
date.toLocaleString() //"22/07/2018, 07:22:13"
date.toLocaleTimeString() //"07:22:13"
date.getTime() //1532236933000
date.getTime() //1532236933000

日期对象的获取器方法

日期对象提供了几种方法来检查其值。这些都取决于计算机的当前时区:

1
2
3
4
5
6
7
8
9
10
11
12
const date = new Date('July 22, 2018 07:22:13')

date.getDate() //22
date.getDay() //0(0表示星期天,1表示星期一..)
date.getFullYear() //2018
date.getMonth() //6(从0开始)
date.getHours() //7
date.getMinutes() //22
date.getSeconds() //13
date.getMilliseconds() //0(未指定)
date.getTime() //1532236933000
date.getTimezoneOffset() //-120(取决于您所在位置和检查的时间 - 在夏季为CET)。返回表示时区差异的分钟数

这些方法都有等效的UTC版本,返回的是与您当前时区适应的值,而不是UTC值:

1
2
3
4
5
6
7
8
date.getUTCDate() //22
date.getUTCDay() //0(0表示星期天,1表示星期一..)
date.getUTCFullYear() //2018
date.getUTCMonth() //6(从0开始)
date.getUTCHours() //5(不是上面的7)
date.getUTCMinutes() //22
date.getUTCSeconds() //13
date.getUTCMilliseconds() //0(未指定)

编辑日期

日期对象提供了几种方法来编辑日期值:

1
2
3
4
5
6
7
8
9
10
const date = new Date('July 22, 2018 07:22:13')

date.setDate(newValue)
date.setFullYear(newValue) //注意:避免使用setYear(),它已被弃用
date.setMonth(newValue)
date.setHours(newValue)
date.setMinutes(newValue)
date.setSeconds(newValue)
date.setMilliseconds(newValue)
date.setTime(newValue)

setDatesetMonth从0开始计数,所以例如3月是第2个月。

例如:

1
2
3
4
const date = new Date('July 22, 2018 07:22:13')

date.setDate(23)
date // July 23, 2018 07:22:13

有趣的是,这些方法是“重叠”的,所以如果您设置了date.setHours(48),那么日期也会增加一天。

好知道的是,您可以向setHours()添加多个参数,以同时设置分钟、秒和毫秒:setHours(0, 0, 0, 0) - 对于setMinutessetSeconds也是如此。

与get *方法类似,set *方法也有一个UTC等效方法,可以返回UTC值而不是适应您当前时区的值:

1
2
3
4
5
6
7
8
9
10
const date = new Date('July 22, 2018 07:22:13')

date.setUTCDate(newValue)
date.setUTCDay(newValue)
date.setUTCFullYear(newValue)
date.setUTCMonth(newValue)
date.setUTCHours(newValue)
date.setUTCMinutes(newValue)
date.setUTCSeconds(newValue)
date.setUTCMilliseconds(newValue)

获取当前时间戳

如果您想获取当前时间戳的毫秒数,您可以使用以下简写:

1
Date.now()

而不是:

1
new Date().getTime()

JavaScript会尽力工作

请注意。如果您超出一个月的天数,将没有错误,并且日期将进入下个月:

1
new Date(2018, 6, 40) //Thu Aug 09 2018 00:00:00 GMT+0200(中欧夏令时)

月份、小时、分钟、秒和毫秒也是如此。

根据区域设置格式化日期

国际化API在现代浏览器中得到了很好的支持(值得注意的是:UC浏览器是一个明显的例外),它允许您翻译日期。

这是由Intl对象公开的,它还有助于本地化数字、字符串和货币。

我们感兴趣的是Intl.DateTimeFormat()

下面是如何使用它。

根据计算机默认区域设置格式化日期:

1
2
3
// "12/22/2017"
const date = new Date('July 22, 2018 07:22:13')
new Intl.DateTimeFormat().format(date) //"22/07/2018" in my locale

根据不同的区域设置格式化日期:

1
new Intl.DateTimeFormat('en-US').format(date) //"7/22/2018"

Intl.DateTimeFormat方法接受一个可选参数,允许您自定义输出。要同时显示小时、分钟和秒,可以使用以下方法:

1
2
3
4
5
6
7
8
9
10
11
const options = {
year: 'numeric',
month: 'numeric',
day: 'numeric',
hour: 'numeric',
minute: 'numeric',
second: 'numeric'
}

new Intl.DateTimeFormat('en-US', options).format(date) //"7/22/2018, 7:22:13 AM"
new Intl.DateTimeFormat('it-IT', options2).format(date) //"22/7/2018, 07:22:13"

这里是您可以使用的所有属性的参考

比较两个日期

您可以使用Date.getTime()计算两个日期之间的差异:

1
2
3
const date1 = new Date('July 10, 2018 07:22:13')
const date2 = new Date('July 22, 2018 07:22:13')
const diff = date2.getTime() - date1.getTime() //以毫秒为单位的差异

同样,您可以检查两个日期是否相等:

1
2
3
4
5
const date1 = new Date('July 10, 2018 07:22:13')
const date2 = new Date('July 10, 2018 07:22:13')
if (date2.getTime() === date1.getTime()) {
//日期相等
}

请记住getTime()返回毫秒数,所以您需要考虑在比较中的时间。July 10, 2018 07:22:13 不等于新的July 10, 2018。在这种情况下,您可以使用setHours(0, 0, 0, 0)来重置时间。

tags: [“date”, “parsing”, “formatting”, “timezones”, “comparison”]