Keep

深入理解 JavaScript 中的 Date

2020/04/11 02:28

  1. UTC/GMT - 世界协调时间/格林尼治标准时间,UTC 为主要的标准时间,能与GMT时间互换,按相同处理即可。
  2. 本地时间/当地时间 - 本地/当地只是一个相对概念,一般本地是指说话人所在地区,而当地是某人所在或某事发生的地方。而本地时间/当地时间指某地的时间,比如北京时间 2020-04-11 12:51,纽约时间 2020-04-11 00:51,这两个时间都是 UTC 时间 2020-04-11 08:51,也就是说北京/纽约的时间和标准时间表示存在偏移。
  3. 时区/时差/UTC偏移量 - 本地时间/当地时间相对于 UTC 时间的偏移量。使用 Zone Name 表示偏移量相同的多个地方,比如 Asia/Shanghai 对应中国的偏移量 +08:00,但由于存在夏令时,偏移量会调整 - 参考。存在不同国家地区但偏移量相同,为了方便描述/沟通,也会存在多个 Zone Name 对应相同的偏移量。
  4. 夏令时(DST/CDT) - 政策性调整时间的表示,具体可参加 wiki。由于是政策性调整时间,在程序代码里需要有一份表格(配置)来记录每次调整 - iana.org 会记录全世界内的调整记录,比如中国 1986-1991 期间夏令时。那么在程序处理 date 时,只需要调整 UTC 偏移量即可。另外,由于全世界范围内所有时间都记录在表格上,数据量很大,可根据业务具体需求做数据裁剪 - 比如 moment-timezone 默认已裁剪几段数据可供选择。
  5. 时间戳(timestamp),一般指的是 Unix 时间,即从1970年1月1日0时0分0秒起至现在的总秒数,更早的时间就是负数。
  6. JavaScript 语言支持下面 6 个 Level 的 date/time 格式:

    1. YYYY ex: 2020
    2. YYYY-MM ex: 2020-04
    3. YYYY-MM-DD ex: 2020-04-11
    4. YYYY-MM-DDThh:mmTZD ex: 2020-04-11T12:32+08:00,2020-04-11T04:32Z
    5. YYYY-MM-DDThh:mm:ssTZD ex: 2020-04-11T12:32:12+08:00,2020-04-11T04:32:12Z
    6. YYYY-MM-DDThh:mm:ss.sTZD ex: 2020-04-11T12:32:12.25+08:00,2020-04-11T04:32:12.100Z

    ps: 不建议使用其他格式

  7. JavaScript 语言内置 Date 类,支持读取 Local date/time 以及UTC date/time方法。实例化后得到的是本地时间对象,ex:

    1. 获取本地时间实例: new Date(2020, 3, 30) 在 +08:00 时区运行得到 2020-04-29T16:00:00.000Z
    2. 获取标准时间实例: new Date(new Date.UTC(2020, 3, 30)) 在 +08:00 时区运行得到 2020-04-30T00:00:00.000Z
    3. 根据字符串实例化: new Date('2020-04-11T12:32:12+08:00') - 为了兼容,建议只使用 6 提到的格式
    4. api 中特殊处理: new Date(2020, 4, 0, 12, 60, 60) 在+08:00 本地运行会得到 2020-04-30T05:01:00.000Z
  8. 使用上面提到的 6 种格式外的其他格式会怎么样?

    1. Safari 下执行 new Date(‘2020-04-11 12:12:12’) 会报 Invalid Date 错误。字符串 2020-04-11 12:12:12 不是 JavaScript 标准支持的格式,不同宿主环境下,实现不一致导致的。
    2. new Date(‘2020-04-11’) 和 new Date(‘2020-4-11’) 是有区别的,前者是标准时间,后者是本地时间。比如在 Asia/Shanghai, 执行上面语句会分别得到:Sat Apr 11 2020 08:00:00 GMT+0800 (China Standard Time)Sat Apr 11 2020 00:00:00 GMT+0800 (China Standard Time)
  9. 本地时间和当地时间转换,比如已知北京时间 2020-04-11T14:10:30+08:00,转换为America/New_York 时间:

    1. 根据当地时间得到标准时间 2020-04-11T06:10:30Z 或者时间戳 1586585430
    2. 通过查表,America/New_York 得到 timeZone 配置 - 因为可能存在夏令时,偏移量不是固定值
    3. 根据标准时间和 timeZone 配置得到 UTC 偏移量 - 1604210400000/240 即,UTC-4
    4. 根据标准时间和偏移量,计算得到本地时间 - 2020-04-11T02:10:30-04:00
  10. 个性化显示 - 日期/时间在不同语言(locales)情景下,显示的是不同的。比如,week 在中文语言下会显示星期。对此,JavaScript 内置 Intl.DateTimeFormat 来处理,当然也有很多库(ex: date-fns, moment, dayjs…)来做 format。
  11. 几个标准定义

    1. 每周从星期一开始
    2. 每年第一周定义:第一个星期四所在的周为第一周。周日历参考

参考


Redky,生活在北京(北漂),程序员,宅,喜欢动漫(海贼王)。"年轻骑士骑马出城,不曾见过绝望堡下森森骸骨,就以为自己可以快意屠龙拯救公主。"