【问题标题】:MongoDB ISODate() gives different results than Date()?MongoDB ISODate() 给出的结果与 Date() 不同?
【发布时间】:2017-04-01 16:10:22
【问题描述】:

通过阅读docs,我的印象是 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)

为什么第一个日期和最后一个日期不同?我可以看到我在某处明显溢出了 something。此外,Mongo 可以支持的最小和最大日期是多少?

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

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

【问题讨论】:

    标签: javascript mongodb date datetime mongodb-query


    【解决方案1】:

    对于范围部分,docs 中提到。

    在内部,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 函数中的正则表达式(它只期望正常日期)运行的。

    /(\d{4})-?(\d{2})-?(\d{2})(T (:?(\d{2})(:?(\d{2}(.\d+)?))?)?(Z|([+-])(\d{2}):?(\ d{2})?)?)?/

    当正则表达式针对日期执行时,它会产生三组。

    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。

    【讨论】:

      【解决方案2】:

      使用 MongoDB Shell(嵌入在流星中)

      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 instance that represents a single moment in time. Date objects are based on a time value that is the number of milliseconds since 1 January, 1970 UTC.

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

      【讨论】:

      • 这只是一个用于创建某种最小日期的数字(特别是 4 月 19 日,-271821 日期)。从那以后我一直在解决它,但很好奇为什么会发生这种行为。
      • 您需要 1970 年之前的日期,精度为毫秒吗?我建议使用new Date(0)ISODate("1970-01-01T00:00:00Z")
      • 那行得通,是的。但我已经改变了我的方法。这个问题更多是出于对差异的好奇,而不是试图解决我的问题。
      猜你喜欢
      • 2011-10-22
      • 2023-04-08
      • 2022-01-25
      • 2015-12-02
      • 1970-01-01
      • 2019-06-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多