MongoDB ISODate()给出的结果与Date()不同

MongoDB ISODate() gives different results than Date()?

本文关键字:Date 不同 结果 ISODate MongoDB      更新时间:2023-09-26

阅读文档时,我的印象是ISODate只是包装了Date构造函数。然而,我似乎不能让他们正确工作的日期非常,非常远的过去。例如:

new Date(-8640000000000000);                          // Mon Apr 19 -271821 18:00:00 GMT-0600 (Mountain Daylight Time)
new Date(-8640000000000000).toISOString();            // -271821-04-20T00:00:00.000Z
ISODate(new Date(-8640000000000000).toISOString());   // Wed Sep 03 2719 18:00:00 GMT-0600 (Mountain Daylight Time)

为什么第一次约会和最后一次约会不一样?我可以看到,我显然是溢出的东西,某处。另外,Mongo可以支持的最小和最大日期是什么?

编辑:有趣的是,这是预期的工作:

new Date( new Date(-8640000000000000).toISOString()); // Mon Apr 19 -271821 18:00:00 GMT-0600 (Mountain Daylight Time)

对于范围部分,在文档中有提到。

在内部,Date对象存储为64位整数,表示自Unix纪元(1970年1月1日)以来的毫秒数,其中结果得出一个可代表的日期范围约为2.9亿年过去和未来。

让我们来分析一下你有什么。我会在mongo shell上运行所有内容。

new Date(-8640000000000000); //ISODate("-271821-04-20T00:00:00Z")
new Date(-8640000000000000).toISOString(); // -271821-04-20T00:00:00.000Z
ISODate(new Date(-8640000000000000).toISOString()); //ISODate("2719-09-04T00:00:00Z")

让我们分析最后一个日期的输出。解析new Date(-8640000000000000). toisostring()后,输出-271821-04-20T00:00:00.000Z将通过ISODate函数传递。

先前获得的结果通过ISO Date函数中的regex(它只期望正常日期)运行。

/(' d {4}) ? (' d {2}) ? (' d {2}) (T(: ? (' d {2}) (: ? (' d {2} (' d +) ?)) ?) ? (Z | ((+ -)) (' d {2}): ? (' d{2}) ?)吗?)?/

当对date执行regex时,结果为三组

Full match  0-9 `271821-04`
Group 1.    0-4 `2718`
Group 2.    4-6 `21`
Group 3.    7-9 `04`

所以ISODate将这些输入传递给javascript Date。UTC构造函数,它的年为2718,月为21,月中的一天为4。javascript方法将月21处理为1年和9个月,因此它将偏移量1添加到2718,将年更改为2719,将月更改为9,日期为4。

最终输出日期为2719-09-04

使用MongoDB Shell(嵌入在meteor中)

meteor:PRIMARY> new Date(1479424285700)
ISODate("2016-11-17T23:11:25.700Z")
meteor:PRIMARY> ISODate(new Date(1479424285700).toISOString());
ISODate("2016-11-17T23:11:25.700Z")

按预期工作,两者返回相同的日期。

为什么要将-8640000000000000传递给日期构造函数?你想创建的日期是什么?

JavaScript Date实例,表示时间中的单个时刻。日期对象基于时间值,即毫秒数自1970年1月1日起

我建议在规范中不包括向构造函数传递负值,如果这样做,您可能会得到意想不到的结果。