内建对象:日期(Date)。该对象存储日期和时间,并提供了日期/时间的管理方法。
我们可以使用它来存储创建/修改时间,测量时间,或者仅用来打印当前时间。
1、创建
调用 new Date()
来创建一个新的 Date
对象。在调用时可以带有一些参数,如下所示:
new Date()
不带参数 —— 创建一个表示当前日期和时间的 Date
对象:
let now = new Date();
alert( now ); // 显示当前的日期/时间
new Date(milliseconds)
创建一个 Date
对象,其时间等于 1970 年 1 月 1 日 UTC+0 之后经过的毫秒数(1/1000 秒)。
// 0 表示 01.01.1970 UTC+0
let Jan01_1970 = new Date(0);
alert( Jan01_1970 );// 现在增加 24 小时,得到 02.01.1970 UTC+0
let Jan02_1970 = new Date(24 * 3600 * 1000);
alert( Jan02_1970 );
传入的整数参数代表的是自 1970-01-01 00:00:00 以来经过的毫秒数,该整数被称为 时间戳。
这是一种日期的轻量级数字表示形式。我们通常使用 new Date(timestamp)
通过时间戳来创建日期,并可以使用 date.getTime()
将现有的 Date
对象转化为时间戳(下文会讲到)。
在 01.01.1970 之前的日期带有负的时间戳,例如:
// 31 Dec 1969
let Dec31_1969 = new Date(-24 * 3600 * 1000);
alert( Dec31_1969 );
new Date(datestring)
如果只有一个参数,并且是字符串,那么它会被自动解析。该算法与 Date.parse
所使用的算法相同,将在下文中进行介绍。
let date = new Date("2017-01-26");
alert(date);
// 未指定具体时间,所以假定时间为格林尼治标准时间(GMT)的午夜零点
// 并根据运行代码时的用户的时区进行调整
// 因此,结果可能是
// Thu Jan 26 2017 11:00:00 GMT+1100 (Australian Eastern Daylight Time)
// 或
// Wed Jan 25 2017 16:00:00 GMT-0800 (Pacific Standard Time)
new Date(year, month, date, hours, minutes, seconds, ms)
使用当前时区中的给定组件创建日期。只有前两个参数是必须的。
year
应该是四位数。为了兼容性,也接受 2 位数,并将其视为19xx
,例如98
与1998
相同,但强烈建议始终使用 4 位数。month
计数从0
(一月)开始,到11
(十二月)结束。date
是当月的具体某一天,如果缺失,则为默认值1
。- 如果
hours/minutes/seconds/ms
缺失,则均为默认值0
。
new Date(2011, 0, 1, 0, 0, 0, 0); // 1 Jan 2011, 00:00:00
new Date(2011, 0, 1); // 同样,时分秒等均为默认值 0
时间度量最大精确到 1 毫秒(1/1000 秒)
let date = new Date(2011, 0, 1, 2, 3, 4, 567);
alert( date ); // 1.01.2011, 02:03:04.567
2、访问日期组件
从 Date 对象中访问年、月等信息有多种方式:
getFullYear()
获取年份(4 位数)
getMonth()
获取月份,从 0 到 11。
getDate()
获取当月的具体日期,从 1 到 31,这个方法名称可能看起来有些令人疑惑。
getHours(),getMinutes(),getSeconds(),getMilliseconds()
获取相应的时间组件。
不是
getYear()
,而是getFullYear()
很多 JavaScript 引擎都实现了一个非标准化的方法
getYear()
。不推荐使用这个方法。它有时候可能会返回 2 位的年份信息。永远不要使用它。要获取年份就使用getFullYear()
。
另外,我们还可以获取一周中的第几天:
getDay()
获取一周中的第几天,从 0
(星期日)到 6
(星期六)。第一天始终是星期日,在某些国家可能不是这样的习惯,但是这不能被改变。
以上的所有方法返回的组件都是基于当地时区的。
当然,也有与当地时区的 UTC 对应项,它们会返回基于 UTC+0 时区的日、月、年等:getUTCFullYear(),getUTCMonth(),getUTCDay()。只需要在 "get"
之后插入 "UTC"
即可。
如果你当地时区相对于 UTC 有偏移,那么下面代码会显示不同的小时数:
// 当前日期
let date = new Date();// 当地时区的小时数
alert( date.getHours() );// 在 UTC+0 时区的小时数(非夏令时的伦敦时间)
alert( date.getUTCHours() );
除了上述给定的方法,还有两个没有 UTC 变体的特殊方法:
getTime()
返回日期的时间戳 —— 从 1970-1-1 00:00:00 UTC+0 开始到现在所经过的毫秒数。
getTimezoneOffset()
返回 UTC 与本地时区之间的时差,以分钟为单位.
// 如果你在时区 UTC-1,输出 60
// 如果你在时区 UTC+3,输出 -180
alert( new Date().getTimezoneOffset() );
3、设置时间组件
下列方法可以设置日期/时间组件:
- setFullYear(year, [month], [date])
- setMonth(month, [date])
- setDate(date)
- setHours(hour, [min], [sec], [ms])
- setMinutes(min, [sec], [ms])
- setSeconds(sec, [ms])
- setMilliseconds(ms)
- setTime(milliseconds)(使用自 1970-01-01 00:00:00 UTC+0 以来的毫秒数来设置整个日期)
以上方法除了 setTime()
都有 UTC 变体,例如:setUTCHours()
。
我们可以看到,有些方法可以一次性设置多个组件,比如 setHours
。未提及的组件不会被修改。
举个例子:
let today = new Date();today.setHours(0);
alert(today); // 日期依然是今天,但是小时数被改为了 0today.setHours(0, 0, 0, 0);
alert(today); // 日期依然是今天,时间为 00:00:00。
4、自动校准
自动校准 是 Date 对象的一个非常方便的特性。我们可以设置超范围的数值,它会自动校准。
举个例子:
let date = new Date(2013, 0, 32); // 32 Jan 2013 ?!?
alert(date); // ……是 1st Feb 2013!
超出范围的日期组件将会被自动分配。
假设我们要在日期 “28 Feb 2016” 上加 2 天。结果可能是 “2 Mar” 或 “1 Mar”,因为存在闰年。但是我们不需要考虑这些,只需要直接加 2 天,剩下的 Date 对象会帮我们处理:
let date = new Date(2016, 1, 28);
date.setDate(date.getDate() + 2);alert( date ); // 1 Mar 2016
这个特性经常被用来获取给定时间段后的日期。例如,我们想获取“现在 70 秒后”的日期:
let date = new Date();
date.setSeconds(date.getSeconds() + 70);
alert( date ); // 显示正确的日期信息
我们还可以设置 0 甚至可以设置负值。例如:
let date = new Date(2016, 0, 2); // 2016 年 1 月 2 日date.setDate(1); // 设置为当月的第一天
alert( date );date.setDate(0); // 天数最小可以设置为 1,所以这里设置的是上一月的最后一天
alert( date ); // 31 Dec 2015
日期转化为数字,日期差值
当 Date 对象被转化为数字时,得到的是对应的时间戳,与使用 date.getTime() 的结果相同:
let date = new Date();
alert(+date); // 以毫秒为单位的数值,与使用 date.getTime() 的结果相同
有一个重要的副作用:日期可以相减,相减的结果是以毫秒为单位时间差。
这个作用可以用于时间测量:
let start = new Date(); // 开始测量时间// do the job
for (let i = 0; i < 100000; i++) {let doSomething = i * i * i;
}let end = new Date(); // 结束测量时间alert( `The loop took ${end - start} ms` );
Date.now()
如果我们仅仅想要测量时间间隔,我们不需要 Date 对象。
有一个特殊的方法 Date.now(),它会返回当前的时间戳。
它相当于 new Date().getTime(),但它不会创建中间的 Date 对象。因此它更快,而且不会对垃圾回收造成额外的压力。
这种方法很多时候因为方便,又或是因性能方面的考虑而被采用,例如使用 JavaScript 编写游戏或其他的特殊应用场景。
因此这样做可能会更好:
let start = Date.now(); // 从 1 Jan 1970 至今的时间戳// do the job
for (let i = 0; i < 100000; i++) {let doSomething = i * i * i;
}let end = Date.now(); // 完成alert( `The loop took ${end - start} ms` ); // 相减的是时间戳,而不是日期