A Roadmap
  • Introduction
  • Roadmap
  • Basics
    • Basic Terminal Usage
      • Shell
        • 基本
        • 变量
        • 传递参数
        • 运算符
        • 命令
        • 流程控制
        • 函数
        • 输入输出重定向
    • Character Encoding
      • 字符编码
    • Data Structures & algorithms
    • Network
      • TCP/IP
      • Http/Https
        • 浏览器缓存
        • Status Code
        • GET & POST
        • HTTPS 握手过程
        • HostOnly Cookie
      • CDN
        • CDN 工作原理
    • Version Control
      • git message format
      • git commands
    • Principles
    • Design Patterns
    • Others
      • JSON
      • 正则表达式
  • Front End
    • Web Standard
      • Html
      • CSS
        • font-face 小记
        • Grid 布局简易笔记
      • Javascript
        • Ajax
          • Fetch
          • XMLHttpRequest
        • DOM
          • Selection
          • 常用 DOM 操作
          • script 标签的几个属性
        • Ecmascript
          • this 关键字
          • Event Loop
          • 隐式转换
          • Date
        • Event
          • 模拟事件
          • Others
    • Development
      • Package Management
        • npm
      • Modulization
        • 模块化机制
        • webpack 打包解析
      • Architecture
      • Build Tools
        • 如何编写一个自定义的 eslint 规则?
      • Debug
        • 移动端调试 web
      • Pre/Post Processors
      • Test
        • Jest Snapshot 使用指南
      • Type Checkers
        • TS 中 enum 的编译结果
    • Libs & frameworks
    • Platforms
      • Browser
        • Basics
          • 从输入 URL 到页面加载完成都发生了什么事情?
          • HTML 加载的过程示意图
          • 为什么读取某些属性,也会导致回流?
          • Chrome 进程模型
        • PWA
        • Compatible
        • Cross Origin
        • Performance
          • 性能检测:performance 对象
          • 性能指标
        • Others
          • 移动端 web 开发笔记
      • Server
      • Desktop Applications
      • Mobile Applications
        • Flutter 在移动端和 Web 端的技术实现
  • Back End
    • outline
    • Languages
      • Node
        • Event Loop
        • NodeJS 中的进程与线程
        • NodeJS 中的 esModule 与 commonJS
  • Clients
    • outline
    • 安装 IPA 包
  • DevOps
    • Languages
    • OS Concepts
    • Servers & terminal
  • UI & UX
    • outline
  • Others
    • Posts
      • 使用 node 爬取数据并导出到 excel
      • antd 1.x datepicker 时区问题
      • babel-transform-runtime 踩坑记录
      • lodash 按需加载注意事项
      • 记一次项目迁移的踩坑记录
      • 时区与JS中的Date对象
      • 记一次 vue + ts 开发踩坑
    • Tools
      • 个人常用的工具分享
      • tmux 简要笔记
Powered by GitBook
On this page
  • TL;DR
  • Background
  • How to create a date instance
  • Different params given to new Date lead to different results
  • Conclusion

Was this helpful?

  1. Front End
  2. Web Standard
  3. Javascript
  4. Ecmascript

Date

Previous隐式转换NextEvent

Last updated 3 years ago

Was this helpful?

2018年11月19日 12:40:00

TL;DR

  1. new Date("2018-11-19") 和 new Date("2018-11-19 00:00:00") 的返回结果可能是不一样的。

  2. 如果需要创建一个日期对象,且希望不同时区下创建的该对象,都能展示为同一天,尽量加上 00:00:00 ,或者使用 new Date(y, [m, [d, [...]]])、 moment("2018-11-19").toDate()

Background

在某个项目中,前后端通信的时候,后端返回给前端一个 形如 yyyy-mm-dd hh:mm:ss 的字符串,如下所示:

antd@1.x的datepicker需要一个date对象或者字符串作为初始值。如果我们要传date对象的话,就需要手动把上面的entry_date字符串,转化为一个date对象。

为什么传date对象而不是字符串:因为antd@1.x用了一个GregoryDate库,这个库内部时间处理对时区、夏令时支持很不友好,容易出问题,所以antd@2.x之后已经改为了moment

How to create a date instance

说起创建一个date对象,大家可能会想到new Date() 或者 Date()。不过只有前者才返回一个date对象,后者返回的是一个字符串。

那么下列代码分别会返回哪些值呢?:

new Date("2018-11-19")
new Date("2018-11-19 00:00:00")
new Date(2018, 10, 19)
new Date(2018, 10, 19, 0, 0, 0)

如果我们在东八区执行下列代码,得到的结果如下(注意看参数和返回结果中时间的对应关系):

new Date("2018-11-19")
// Mon Nov 19 2018 08:00:00 GMT+0800 (中国标准时间)

new Date("2018-11-19 00:00:00")
// Mon Nov 19 2018 00:00:00 GMT+0800 (中国标准时间)

new Date(2018, 10, 19)
// Mon Nov 19 2018 00:00:00 GMT+0800 (中国标准时间)

new Date(2018, 10, 19, 0, 0, 0)
// Mon Nov 19 2018 00:00:00 GMT+0800 (中国标准时间)

第一项的时间似乎不太对劲,但是整体看来也没什么问题。 可是如果我们在西八区执行这段代码会怎样呢?

new Date("2018-11-19")
// Sun Nov 18 2018 16:00:00 GMT-0800 (北美太平洋标准时间)

new Date("2018-11-19 00:00:00")
// Mon Nov 19 2018 00:00:00 GMT-0800 (北美太平洋标准时间)

new Date(2018, 10, 19)
// Mon Nov 19 2018 00:00:00 GMT-0800 (北美太平洋标准时间)

new Date(2018, 10, 19, 0, 0, 0)
// Mon Nov 19 2018 00:00:00 GMT-0800 (北美太平洋标准时间)

仔细一看,会发现第一项不仅时间与其他项不一样,最重要的是时间也不一样了。 这就导致不同时区的用户在 antd@1.x 的 datepicker 中看到的日期会不一样。

Different params given to new Date lead to different results

是什么原因导致了这一问题呢?MDN中已经明确说明了:

单独使用一个日期,而不加任何别的参数,会被认为是UTC时间。

不清楚协调时间UTC、格林尼治时间GMT、夏令时 DST 的同学,可以参考下面的文章:

- [The Difference Between GMT and UTC](https://www.timeanddate.com/time/gmt-utc-time.html)
- [GMT、UTC与24时区 等时间概念](https://blog.csdn.net/webcainiao/article/details/4018761)

事实上大家也不用关心 GMT,二者在js,或者说浏览器中,差别不是太大

- The JavaScript ​Date​ object supports a number of UTC (universal) methods, as well as local time methods. UTC, also known as Greenwich Mean Time (GMT), refers to the time as set by the World Time Standard. The local time is the time known to the computer where JavaScript is executed.

也就是说,下列代码是等同的:(P.S. new Date()的返回值,是按照本地时间进行展示的)

new Date("2018-11-19")
// Sun Nov 18 2018 16:00:00 GMT-0800 (北美太平洋标准时间)

new Date('Mon Nov 19 2018 00:00:00 GMT+0000')
// Sun Nov 18 2018 16:00:00 GMT-0800 (北美太平洋标准时间)

当我们在使用 new Date('2018-11-19') 创建一个date对象时,实际上就是在创建一个时区为 GMT+0,时间是2018-11-19 00:00:00的date对象。格林尼治的凌晨时分,对应到西八区,自然就是2018-11-18 16:00:00.也就出现了上述 HR 看到的日期少一天的问题。

Conclusion

  1. 尽量避免 new Date('yyyy-mm-dd') 的用法

  2. 如果需要创建一个日期对象,且希望不同时区下创建的该对象,都能展示为同一天,尽量加上 00:00:00 ,或者使用 new Date(y, [m, [d, [...]]])、 moment("2018-11-19").toDate()