资讯专栏INFORMATION COLUMN

JavaScript Date.parse 的小坑

MRZYD / 668人阅读

摘要:经过一步步后发现问题在此客户时区为美国东部时区夏令时明明写的号,为什么生成的对象是号的因为把它解析为,时区为。美国东部时区是减小时的,于是就变成了前一天。可以传入一个日期字符串来生成对象的,官方规定日期字符串需要符合或者的格式。

TL;DR

new DateDate.parse 在格式化某些日期字符串的时候,时区具有不确定性,最好用 moment.js 这类工具去处理。

不确定的日期字符串

事情的起源是客户跟我说网页上的某个日期总是比实际日期少一天。经过一步步 debug 后发现问题在此:

js// 客户时区为美国东部时区夏令时
new Date("2015-03-31")    // Mon Mar 30 2015 20:00:00 GMT-0400 (EDT)

明明写的 31 号,为什么生成的对象是 30 号的?因为 new Date 把它解析为 2015-03-31 00:00:00 ,时区为 UTC 。美国东部时区是减 4 小时的,于是就变成了前一天 20:00:00 。

那么 new Date 传入的时间字符串有没有规律可循呢?

混乱的规律

new DateDate.parse 使用的是同样的解析规律,只是一个返回 Date object 另一个返回毫秒数。为了方便查看结果,以下例子只用 new Date 。但请记住它们遵循一样的规律。

new Date 可以传入一个日期字符串来生成对象的,官方规定日期字符串需要符合 RFC2822 或者 ISO8601 的格式。拿上面的日期举个例子,前者可以写成 "Mar 31 2015" 后者可以写成 "2015-03-31" 。

如果日期字符串不符合这两种标准,new Date 对结果概不负责……

不过就算符合标准了,结果还是有点不同的。看几个例子:

jsnew Date("Mar 31 2015")    // Tue Mar 31 2015 00:00:00 GMT-0400 (EDT)
new Date("2015-03-31")     // Mon Mar 30 2015 20:00:00 GMT-0400 (EDT)

RFC2822 的格式如果不带时区,new Date 会当做本地时区处理,而 ISO8601 格式则会当做 UTC 时区处理。

是有点绕人,但只要记住这个规律不就完了吗?骚年你太天真了…… 因为 ES6 草案为了简化这种情况,规定所有不带时区的字符串都默认为本地时区。注意这是草案,所以结果你懂的。

解决方案

一种解决方案是每次格式化日期都严格指定时区,以防止各种幺蛾子情况出现,比如:

jsnew Date("2015-03-31T00:00:00-04:00")    // Tue Mar 31 2015 00:00:00 GMT-0400 (EDT)

不过鉴于人都是懒惰的,这种情况交给工具做更靠谱,比如 moment.js 。

jsmoment("2015-03-31").toDate()
参考链接

Date.parse() - JavaScript | MDN

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/85605.html

相关文章

  • JavaScript Dates 终极指南

    摘要:对象对象实例表示单个时间点尽管名为它同样被用来处理时间。在内部日期表示自年月日起到现在的毫秒数。这意味着传入相同的参数在不同电脑上可能会有不同的结果。在没有任何有关时区的信息的情况下会将日期视为结果会自动针对当前的计算机时区进行转换。 在 JavaScript 中处理日期可能会很复杂,我们一起学习 Dates 所有的怪癖并掌握如何使用它。 简介 在 JavaScript 中处理日期可能...

    魏宪会 评论0 收藏0
  • JavaScript 日期权威指南

    摘要:在内部,日期以年月日以来的毫秒数表示。以毫秒为单位记录原因。你也可以使用将返回一个时间戳以毫秒为单位而不是对象。如果您使用天数计算超过一个月,则不会出现错误,日期将转到下个月数月,小时,分钟,秒和毫秒都是如此。 简介showImg(https://segmentfault.com/img/bVbfH0e?w=777&h=512); JavaScript通过强大的对象为我们提供日期处理功...

    ssshooter 评论0 收藏0
  • JavaScript 日期权威指南

    摘要:在内部,日期以年月日以来的毫秒数表示。以毫秒为单位记录原因。你也可以使用将返回一个时间戳以毫秒为单位而不是对象。如果您使用天数计算超过一个月,则不会出现错误,日期将转到下个月数月,小时,分钟,秒和毫秒都是如此。 简介showImg(https://segmentfault.com/img/bVbfH0e?w=777&h=512); JavaScript通过强大的对象为我们提供日期处理功...

    用户83 评论0 收藏0
  • JavaScript 日期权威指南

    摘要:在内部,日期以年月日以来的毫秒数表示。以毫秒为单位记录原因。你也可以使用将返回一个时间戳以毫秒为单位而不是对象。如果您使用天数计算超过一个月,则不会出现错误,日期将转到下个月数月,小时,分钟,秒和毫秒都是如此。 简介showImg(https://segmentfault.com/img/bVbfH0e?w=777&h=512); JavaScript通过强大的对象为我们提供日期处理功...

    xuexiangjys 评论0 收藏0
  • Javascript---Date类型和Math类型

    摘要:而实际上将表示日期的字符串传递给构造函数,也会在后台调用。如果省略其他参数,则统统假设为时间年月日午夜时时间年月日下午构造函数也会模仿,但有一点明显不同日期和时间都基于本地时区而非创建。不过构造函数仍与接收的参数相同。 Date类型 ECMASCript中的Date类型是在早期中Java中的java.util.Date类基础上构建的。为此Date类型使用自UTC(国际协调时间)1970...

    xiaolinbang 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<