早读笔记:JavaScript 标准内置对象 Date

上周,业务报了个 IE 兼容性的 bug,原本想据理力争,当初项目定位只要求兼容 chrome 。但产品说,业务很多人都用的 IE,有用户习惯在。而这个 bug 呢,就是日期格式化传字符串导致的兼容性问题。做移动端项目用 safari 的时候遇到过,这次是 IE。被一个问题坑了两次,真是不应该。

阅读清单

为什么是要读清单中的三条链接?

MDN 上的文章,语言通俗易懂,并提供了典型示例帮助阅读者更好的理解,是很好的入门文档。

如果你需要深入了解更精准的定义,更完整的实现细节,则建议阅读下 ECMAScript 官方标准

最后,了解 dayjs 是来补充前者没有涉及的实战内容:处理浏览器兼容性;已有 API 之外更多实用的方法和技巧。

阅读前提问

  • Date 可以表示任意时间吗?
  • Date 构造函数如何重载?
  • Date()new Date() 的区别?
  • 各浏览器实现上有哪些差异?

相关概念

  • 世界时 GMT
  • 国际原子时 TAI
  • 协调世界时 UTC
  • 闰秒 leap seconds
  • unix epoch
  • 时间戳 timestamps

世界时 GMT

世界时、格林尼治平太阳时间,是指格林尼治所在地的标准时间。以地球自转为基础的时间计量系统。

国际原子时 TAI

一个高精度的原子坐标时间标准,基于地球上的大地水准上的固有时间。针对某些元素的原子能级跃迁频率有极高的稳定性,可采用基于铯原子(Cs 132.9)的能级跃迁原子秒作为时标。

协调世界时 UTC

UTC 是以原子时秒长为基础,在时刻上尽量接近于 GMT 的一种时间计量系统。

TAI 的准确度为每日数纳秒,而 GMT 的准确度为每日数毫秒。许多应用部门要求时间系统接近 GMT,一种称为 UTC 的折衷时标于1972年面世。

闰秒 leap seconds

为确保 UTC 与 GMT 相差不会超过0.9秒,在有需要的情况下会在 UTC 内加上正或负闰秒。一般会在每年的6月30日、12月31日的最后一秒进行调整。

JavaScript 忽略闰秒。

unix epoch

unix 纪元。即,1970-01-01 UTC

时间戳 timestamps

the number of milliseconds that have elapsed since midnight on January 1, 1970, UTC.

常用语法

构造函数

无参数

新创建的日期对象表示实例化时的当前日期和时间。

new Date()          // Date Object
new Date(undefined) // Invalid Date

时间戳字符串

各浏览器实现存在差异,小心使用。支持一下两种格式的字符串:

  • RFC 2822 格式,例如2020/02/02,表示本地时间,这并不是官方标准要求支持的格式,而是 convention only
  • 简化版 ISO 8601 格式,例如2020-02-02T00:00:00.000Z,ES 标准中对此标准做了简化,并未支持全部的格式。注意,年份只支持4位或者6位的格式,具体见标准。

查阅了 ES文档,直到 ES5 才引入了标准的字符串格式的规范,ES3 中并未提及,ES5 发布于 2009 年,IE8 同年也发布了第一个版本,因此猜测这就是为什么 IE 9+ 才支持的原因。

new Date(2020, 1, 2)
// Sun Feb 02 2020 00:00:00 GMT+0800 (中国标准时间)

new Date('2020/02/02')
// RFC 2822 => Sun Feb 02 2020 00:00:00 GMT+0800 (中国标准时间)

new Date('2020-02-02T00:00:00.000Z')
// ISO 8601 => Sun Feb 02 2020 08:00:00 GMT+0800 (中国标准时间)

new Date('2020T00:00')
// ISO 8601 => Wed Jan 01 2020 00:00:00 GMT+0800 (中国标准时间)

其他

new Date(year, monthIndex [, day [, hours [, minutes [, seconds [, milliseconds]]]]])
  • 至少需要输入 yearmonthIndex 两个参数
  • 其他缺省值的默认值:day1,其他为 0
  • year 取值如果在 0-99,则对应的实际值为 1900-1999
  • monthIndex 参数名直观的说明,是一个索引值,从 0 开始

阅读后答疑

Date 可以表示任意时间吗?

Date 对象的范围是 UTC 1970,1,1 前后一百万天,即:公元前271821-04-20 至公元 275760-09-13。

var oneMillionDays = 100000000 * 24 * 60 * 60 * 1000
var max = new Date(oneMillionDays)
var min = new Date(-oneMillionDays)

console.log(max.toString(), min.toString(), max.toUTCString(), min.toUTCString())

// chrome 80.0.3987.149(正式版本) (64 位)

// Sat Sep 13 275760 08:00:00 GMT+0800 (中国标准时间) 
// Tue Apr 20 -271821 08:05:43 GMT+0805 (中国标准时间) 
// Sat, 13 Sep 275760 00:00:00 GMT 
// Tue, 20 Apr -271821 00:00:00 GMT

// IE Edge

// Sat Sep 13 275760 08:00:00 GMT+0800 (中国标准时间) 
// Tue Apr 20 -271821 08:00:00 GMT+0800 (中国标准时间) 
// Sat, 13 Sep 275760 00:00:00 GMT 
// Tue, 20 Apr 271822 B.C. 00:00:00 GMT

// IE 9/10

// Sat Sep 13 08:00:00 UTC+0800 275760 
// Tue Apr 20 08:00:00 UTC+0800 271822 B.C. 
// Sat, 13 Sep 275760 00:00:00 UTC 
// Tue, 20 Apr 271822 B.C. 00:00:00 UTC

// IE 5/7/8

// Sat Sep 13 275760 08:00:00 GMT+0800 
// Tue Apr 20 -271821 08:00:00 GMT+0800 
// Sat, 13 Sep 275760 00:00:00 GMT 
// Tue, 20 Apr -271821 00:00:00 GMT

var maxAdd1 = new Date(oneMillionDays + 1)
var minAdd1 = new Date(-oneMillionDays - 1)

console.log(maxAdd1, minAdd1, maxAdd1.toUTCString(), minAdd1.toUTCString())

// chrome 80.0.3987.149(正式版本) (64 位)
// IE Edge/10/9

// Invalid Date
// Invalid Date
// Invalid Date
// Invalid Date

// IE 5/7/8

// undefined undefined NaN NaN NaN:NaN:NaN GMT+NaNNaN 
// undefined undefined NaN NaN NaN:NaN:NaN GMT+NaNNaN 
// undefined, NaN undefined NaN NaN:NaN:NaN GMT 
// undefined, NaN undefined NaN NaN:NaN:NaN GMT

注意,chrome 里面显示的是 Tue Apr 20 -271821 08:05:43 GMT+0805,为什么会出现 +0805 呢?因为1901年之前,上海时间是+8:05:43的,直到1901年之后,切换为真正的东八区

Date 构造函数如何重载?

new Date()
new Date(value)
new Date(dateString)
new Date(year, monthIndex [, day [, hours [, minutes [, seconds [, milliseconds]]]]])

Date 构造函数支持多种形式的入参,MDN 文档的书写的顺序,并非标准里描述的重载顺序。具体实现见 Date constructor

Date()new Date() 的区别?

If NewTarget is undefined, then

  1. Let now be the Number that is the time value(UTC) identifying the current time.
  2. Return ToDateString(now).

各浏览器实现上有哪些差异?

dayjs 源码

参考

404

528 声望
67 粉丝
0 条评论
推荐阅读
Caching in HTTP 笔记
HTTP is typically used for distributed information systems, where performance can be improved by the use of response caches.

siwuxie阅读 846

手把手教你写一份优质的前端技术简历
不知不觉一年一度的秋招又来了,你收获了哪些大厂的面试邀约,又拿了多少offer呢?你身边是不是有挺多人技术比你差,但是却拿到了很多大厂的offer呢?其实,要想面试拿offer,首先要过得了简历那一关。如果一份简...

tonychen152阅读 17.8k评论 5

封面图
正则表达式实例
收集在业务中经常使用的正则表达式实例,方便以后进行查找,减少工作量。常用正则表达式实例1. 校验基本日期格式 {代码...} {代码...} 2. 校验密码强度密码的强度必须是包含大小写字母和数字的组合,不能使用特殊...

寒青56阅读 8.5k评论 11

JavaScript有用的代码片段和trick
平时工作过程中可以用到的实用代码集棉。判断对象否为空 {代码...} 浮点数取整 {代码...} 注意:前三种方法只适用于32个位整数,对于负数的处理上和Math.floor是不同的。 {代码...} 生成6位数字验证码 {代码...} ...

jenemy49阅读 7.2k评论 12

从零搭建 Node.js 企业级 Web 服务器(十五):总结与展望
总结截止到本章 “从零搭建 Node.js 企业级 Web 服务器” 主题共计 16 章内容就更新完毕了,回顾第零章曾写道:搭建一个 Node.js 企业级 Web 服务器并非难事,只是必须做好几个关键事项这几件必须做好的关键事项就...

乌柏木75阅读 7.1k评论 16

再也不学AJAX了!(二)使用AJAX ① XMLHttpRequest
「再也不学 AJAX 了」是一个以 AJAX 为主题的系列文章,希望读者通过阅读本系列文章,能够对 AJAX 技术有更加深入的认识和理解,从此能够再也不用专门学习 AJAX。本篇文章为该系列的第二篇,最近更新于 2023 年 1...

libinfs42阅读 6.8k评论 12

封面图
CSS 绘制一只思否猫
欢迎关注我的公众号:前端侦探练习 CSS 有一个比较有趣的方式,就是发挥想象,绘制各式各样的图案,比如来绘制一只思否猫?思否猫,SegmentFault 思否的吉祥物,是一只独一无二、特立独行、热爱自由的(>^ω^&lt...

XboxYan47阅读 3.3k评论 14

封面图

404

528 声望
67 粉丝
宣传栏