深入 JavaScript 时间对象 Date

程序中涉及到时间相关的概念,都比较繁琐且易出错。JavaScript中的浏览器内置的 Date 对象,相比较其他编程 简单易用;相关方法一目了然。

一、Date 原型对象上的方法

Object.getOwnPropertyNames(Date.prototype) //注意这些方法都是不可枚举的
["constructor", "toString", "toDateString", "toTimeString", "toISOString", "toUTCString", "toGMTString", "getDate", "setDate", "getDay", "getFullYear", "setFullYear", "getHours", "setHours", "getMilliseconds", "setMilliseconds", "getMinutes", "setMinutes", "getMonth", "setMonth", "getSeconds", "setSeconds", "getTime", "setTime", "getTimezoneOffset", "getUTCDate", "setUTCDate", "getUTCDay", "getUTCFullYear", "setUTCFullYear", "getUTCHours", "setUTCHours", "getUTCMilliseconds", "setUTCMilliseconds", "getUTCMinutes", "setUTCMinutes", "getUTCMonth", "setUTCMonth", "getUTCSeconds", "setUTCSeconds", "valueOf", "getYear", "setYear", "toJSON", "toLocaleString", "toLocaleDateString", "toLocaleTimeString"]

调用 Date 对象的 getter 方法:

function printDateTable() {
    let date = new Date();
    let tem = {};
    let dateMethodName = Object.getOwnPropertyNames(Date.prototype);
    let dateMethodGet = dateMethodName.filter(m => m.startsWith('to') || m.startsWith('get'));
    dateMethodGet.forEach(m => {
        let dateFormat = date[m].call(date);
        tem[m] = dateFormat;
    });
    console.table(tem);
    return tem;
}

 实际上,了解上述的方法,已经满足大部分业务场景的需要了。值得注意,toString 方法与 toUTCString 方法返回的时间不同,这涉及到两个概念。

二、时间标准与 Unix 时间戳

GMT 时间 即格林威治标准时间;这个时间系统的概念在 1884 年确立。

UTC 协调世界时;利用原子钟计算时间与日期的系统。目前所有的国际通讯系统,卫星、航空、GPS 等,全部采用 UTC 时间。

Unix 时间戳;即自1970年1月1日(UTC)起经过的毫秒数。

通常将 GMT 和 UTC 视作等同。但 UTC 更加科学更加精确。

三、UTC 时间与本地时间

UTC 时间是世界统一时间,世界上同一时刻的 UTC 时间都是相同的,但相同的时刻具体到不同的地区、国家、时间是不一样的,这就是本地时间。

四、JavaScript Date 构造函数参数

Date 构造函数接受四种类型的参数:

1、无参数的构造方法,表示的是实例化时刻的日期和时间;

2、Unix 时间戳,返回的是表示 Unix 时间戳时刻的实例;

3、时间戳字符串,不同的浏览器与不同格式的字符串会导致解析差异;

4、日期时间格式的数字,如 new Date(2020, 5, 26, 18, 25);

五、Date 构造函数参数解析

Date构造函数会根据接受的参数格式与类型,自动判断参数表示的是本地时间还是 UTC 时间;

1、无参数构造方法,

返回的是表示现在时刻的对象,可以自由转换成本地时间和 UTC 时间,在东八区,所以会相差8小时。

new Date()
Mon Jun 01 2020 14:42:13 GMT+0800 (中国标准时间)

2、Unix 时间戳

会被解析成时间戳代表时刻的对象。

let timeStamp = new Date().getTime();
new Date(timeStamp);
Mon Jun 01 2020 14:50:06 GMT+0800 (中国标准时间)

3、时间戳字符串

字符串格式不同,解析的结果不同。

该字符串应该能被 Date.parse() 正确方法识别(即符合 IETF-compliant RFC 2822 timestamps 或 version of ISO8601)。

由于浏览器之间的差异与不一致性,强烈不推荐使用Date构造函数来解析日期字符串 (或使用与其等价的Date.parse)。对 RFC 2822 格式的日期仅有约定俗称的支持。 对 ISO 8601 格式的支持中,仅有日期的串 (例如 "1970-01-01") 会被处理为 UTC 而不是本地时间,与其他格式的串的处理不同。

常用时间字符串解析结果:

function printDateFormat() {
    let dateFormat = ['2020-06-01', '2020/06/01', '2020 06 01', '20200601'];
    let dateTem = {};
    dateFormat.forEach(item => {
        dateTem[item] = new Date(item).toString();
    })
    console.table(dateTem);
}

  • 没有分隔符分割的日期格式,无法被正确识别;
  • 短线分割的日期格式,被处理成了 UTC 时间;
  • 斜线、空格(其他符号分隔符)分割的日期,被处理成本地时间。
function printDateTimeFormat() {
    let dateFormat = [
    'Tue Jun 02 2020 15:54:24 GMT+0800',
    '2020-06-02T07:54:24.271Z', 
    'Tue, 02 Jun 2020 07:54:24 GMT',
    '2020/6/2 下午3:54:24'
  ];
    let dateTem = {};
    dateFormat.forEach(item => {
        dateTem[item] = new Date(item).toString();
    })
    console.table(dateTem);
}

  • 第一种格式被解析成本地时间;
  • 第二、三字符串格式被解析成UTC时间;
  • 本地格式无法被正确解析(不符合ISO8601格式);

4、日期时间数字格式

会被解析成本地时间;

new Date(2020,6,2,15,29,30)
Thu Jul 02 2020 15:29:30 GMT+0800 (中国标准时间)

只传日期数字,时间默认凌晨。(每个参数都有默认值,与主观一致)

new Date(2020,6,2)
Thu Jul 02 2020 00:00:00 GMT+0800 (中国标准时间)

 5、日期格式是否有前缀 0,解析结果不同

new Date('2020-11-4')
//Wed Nov 04 2020 00:00:00 GMT+0800 (中国标准时间)
new Date('2020-11-04')
//Wed Nov 04 2020 08:00:00 GMT+0800 (中国标准时间)
new Date('2020/11/04')
//Wed Nov 04 2020 00:00:00 GMT+0800 (中国标准时间)
new Date('2020/11/4')
//Wed Nov 04 2020 00:00:00 GMT+0800 (中国标准时间)

使用短线分割的格式,天数有前缀0,传入的时间被解析成UTC时间。其余格式均被解析成本地时间。

new Date('2020/09/4')
//Fri Sep 04 2020 00:00:00 GMT+0800 (中国标准时间)
new Date('2020/9/4')
//Fri Sep 04 2020 00:00:00 GMT+0800 (中国标准时间)
new Date('2020-9-4')
//Fri Sep 04 2020 00:00:00 GMT+0800 (中国标准时间)
new Date('2020-09-4')
//Fri Sep 04 2020 00:00:00 GMT+0800 (中国标准时间)

月份则无格式影响,建议解析日期格式要统一。以上代码运行结果均在 chrome 浏览器中 70+ 版本。

 

另:https://www.pianshen.com/article/39621964296/

 

使用 Date 对象时,请注意以下几点:

  • 该 Date 对象内部具有毫秒精度的 Unix 时间戳。它提供了可以在系统本地时区之间来回转换的功能,但是内部始终是 UTC。与 Moment 对象不同,不能将其设置为使用其他时区。它并不存在“模式”的概念。

  • 使用 Date.parse 或 new Date(<string>) 在过去一直存在 bug,且实现不一。当前的规范 支持定义解析 ISO 8601 的字符串,其中只有日期的形式会(如 "2020-09-14")被解析为 UTC,而非 ISO 8601 中的当地时间。即便如此,也不是所有的现代浏览器都会按照这个标准来实现(例如 Safari)。其他类型的字符串也可以使用,但是解析它们是额外实现的,并且可能会有很大的不同,特别是对于旧版本的浏览器来说。实现方式以及传入字符串的不同,可能会产生不同的结果。由于这些原因,我们同意 MDN 的声明,即 强烈反对使用 Date 对象对字符串进行解析

 

参考资料:

GMT与UTC简介,https://www.cnblogs.com/tosee/p/5538007.html

MDN Date,https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Date

posted @ 2020-11-04 10:08  恩恩先生  阅读(417)  评论(0编辑  收藏  举报