Javascript momentJs解析日期:意外行为

Javascript momentJs解析日期:意外行为,javascript,date,momentjs,Javascript,Date,Momentjs,使用momentJs,我遇到了一些我不明白的事情; 让我们来玩一个特定的日期,例如2099-11-11T15:00 将时间转换为日期: > moment('2099-11-11T15:00').toDate() // => Wed Nov 11 2099 15:00:00 GMT+0100 (CET) 将日期转换为时刻: > var d = new Date('2099-11-11T15:00') // => undefined > moment(d)

使用momentJs,我遇到了一些我不明白的事情; 让我们来玩一个特定的日期,例如
2099-11-11T15:00

将时间转换为日期:

> moment('2099-11-11T15:00').toDate()  
// => Wed Nov 11 2099 15:00:00 GMT+0100 (CET)
将日期转换为时刻:

> var d = new Date('2099-11-11T15:00')  
// => undefined  
> moment(d)  
// => { ... _d: Wed Nov 11 2099 16:00:00 GMT+0100 (CET) }
我们有不同的日期,第一个是星期三15:00,第二个是星期三16:00。事实上,如果我们比较它们:

moment(d).isSame(moment('2099-11-11T15:00'))
// => false

乍一看,我以为它与
toDate()
方法有关,但事实并非如此;让我们键入以下内容:

new Date('2099-11-11T15:00').toISOString()
'2099-11-11T15:00:00.000Z'
moment('2099-11-11T15:00').toISOString()
'2099-11-11T14:00:00.000Z'

这里发生了什么?

最后,我决定使用
矩。utc(…)
而不是
矩()
进行每个操作,这样做,两个时间都是相同的:

var d = new Date('2099-11-11T15:00')
var m = moment.utc('2099-11-11T15:00')
m.isSame(moment.utc(d))
// => true
有几件事:

  • 不要注意
    \u d
    字段。下划线字段是moment API的内部字段,可能并不总是您所期望的。在许多函数中,必须结合其他内部字段(如
    \u offset
    )对其进行评估,以生成有效的输出。相反,请使用各种公共函数,如
    格式
    日期
    .valueOf

  • 认识到
    Date
    构造函数解析字符串的方式与矩的解析函数的工作方式有很多不同。别指望他们会匹配

  • 当字符串不包含任何时区信息时,
    矩(…)
    将始终将其视为本地,而
    矩.utc(…)
    将其视为utc。(你的回答就是一个很好的例子。)

  • 日期
    构造函数被赋予一个字符串时,字符串的格式会显著影响解释。实际行为可能因实现而异,但大多数当前浏览器会将连字符和
    T
    视为字符串为ISO8601格式的指示。但是,在没有任何尾随
    Z
    或偏移量的情况下,ES5规范要求将其解释为UTC。ES6已经改变了这一点,它将把这些情况视为本地时间,以更好地符合ISO8601规范。由于不清楚各种环境何时开始实施这一改变,因此谨慎的做法是不要依赖于
    日期
    构造函数

  • 如果希望
    Date
    构造函数将值解释为本地时间(使用ES5),一种方法是使用字符串替换来删除
    T
    ,并用斜杠(
    /
    )替换连字符(
    -
    )。这适用于大多数环境,尽管没有相关规范。(有人告诉我,它在一些Safari浏览器中失败了。)真的,我只会使用Moment的解析函数,而根本不依赖于
    Date
    构造函数