Javascript时间构造的诡异

JavaScript为我们提供了不是很好用的Date作为时间日期对象,除了接口设计怪异之外,还有一些隐藏很深的bug,先看接口设计:

  • Date()直接返回当前时间字符串,无参数。
  • new Date()则是会根据参数来返回对应的时间对象,参数很有意思:
// 无参数,并返回当前时间。
new Date();
// 可接受一个数字参数,该参数表示与1970年1月1日0点之间的毫秒数。
new Date(value);
// 可接受一个字符串参数,参数形式类似于Date.parse()方法。
new Date(dateString);
// 可接受年月日时分秒参数,是本地时间。
new Date(year, month[, day[, hour[, minutes[, seconds[, milliseconds]]]]]);

先且不说这样的接口未免不够灵活(很难处理各种字符串格式的时间),最诡异的一点是其中使用dateString的那个构造方法,MDN网站在这个函数下有下面一段注释:

clipboard.png

注意这里用的是strongly discouraged - 强烈不推荐使用,原先的我没有重视这句话,直到。。。付出惨痛的代价。

现象

我的一款每日打卡类的App,因为有大量的时间运算,为了能接受各种时间,我做了一个方便的函数:

date2ymd(input) {
    let day = (input instanceof Date) ? input : new Date(input)
    return `${day.getFullYear()}-${day.getMonth() + 1}-${day.getDate()}`
}

上面的函数在某些input时没有问题,但当参数为类似’2018-10-1’这种格式,按照MDN的文档,就属于强烈不推荐使用的形式,但我没有留意,App发布之后,不错,大部分用户没有反馈问题,直到某天,一个阿根廷的用户给我邮件反馈,说界面上的日历似乎错乱了,我试着更改自己的时区到对应的-3时区,截图一看:

clipboard.png

上图中彩色小方块的区域是年视图,本来应该和下面的日历一一对应,但在这个时区下,年视图完全错位了,肯定是哪里计算错误了,经过调试,我找到了上面这个函数,并发现了问题,我们用chrome的console演示一下:

clipboard.png

看到了吗? 从9号到10号,转换出的时间没有翻天,当然,我们可以为这种转换找到理由,JS应该是把这种参数当成UTC时间了,我们看看firefox:

clipboard.png

Firefox的表现可以理解,因为UTC和-3:00时区之间有个时间差,虽然这依然不是我想要的,但比起chrome的跳变要好接受一些,我们把输入时间换一个格式,再看下在chrome下的例子:

clipboard.png

这种格式终于符合了正常逻辑,也就是短杠和斜杠分隔的时间处理上是不一致的,斜杠分隔的时间终于正确的按照了本地时间进行处理。

结论

正如MDN所说,不要使用单字符串参数的Date构造函数,即使你知道各种格式之间的区别,也不建议使用,毕竟记忆这些微妙,甚至不兼容的差别毫无意义。

你可能感兴趣的:(Javascript时间构造的诡异)