【问题标题】:What is the best way to store dates of birth in MongoDB?在 MongoDB 中存储出生日期的最佳方法是什么?
【发布时间】:2017-09-18 07:13:51
【问题描述】:

我已经阅读了很多关于如何在 MongoDB 中存储简单日期(没有时间)的文章,但我仍然找不到答案。 有人说像 MongoDate(日期 + utc 时间)一样存储主题,有人说像 YYYYMMDD 字符串一样存储主题,还有一些像其他有趣的方式。最正确的方法似乎是 MongoDate,但是为什么我要将出生日期存储为带有 UTC 时间的日期呢?

另外,出生日期“1990-05-21”存储为“1990-05-20T23:00:00Z”(前一天):此日期不应因时区而改变,但保持不变全世界。

我仍然想知道为什么 MongoDB 不像所有其他数据库那样提供简单的“日期”类型。

【问题讨论】:

  • 如果您想存储生日,那么您可能根本不想存储年份 - 即您可以只存储月份和日期?老实说,这取决于你的用例:你需要存储多少信息,你需要如何查询它,你需要如何比较它们等等。
  • @Vince Bowdren:我需要存储出生日期。 YYYY-MM-DD 显然没有时间。我已经更改了帖子标题。

标签: mongodb date datetime utc


【解决方案1】:
ObjectId("507c7f79bcf86cd7994f6c0e").getTimestamp()

返回:

ISODate("2012-10-15T21:26:17Z")

反正你只是转换时间。

【讨论】:

    【解决方案2】:

    将其存储为一个简单的字符串“1985-21-07”。这听起来可能违反直觉 并点亮你的红色“数据库类型”灯泡,但将出生日期保存为 Date() 会带来许多“部分”(小时、分钟、秒......),这些“部分”没有任何意义,会引起头痛并且在 mongo 中保存和获取出生日期时容易出错。

    在此处阅读最高答案(不是标记为正确的答案): What is the best way to store dates in MongoDB?

    【讨论】:

      【解决方案3】:

      简单使用:

      new Date("<YYYY-mm-dd>");
      

      返回具有指定日期的 ISODate,不带时间戳。 MongoDB 使用 ISO-8601 日期表示法来表示日期对象。这样就提供了很多日期操作。即

      • new Date("&lt;YYYY-mm-dd&gt;") 返回指定日期的 ISODate。

      • new Date("&lt;YYYY-mm-ddTHH:MM:ss&gt;") 指定客户端本地时区 中的日期时间,并返回具有UTC 中指定日期时间的ISODate。

      • new Date("&lt;YYYY-mm-ddTHH:MM:ssZ&gt;") 以 UTC 格式指定日期时间,并以 UTC 格式返回具有指定日期时间的 ISODate。

      • new Date(&lt;integer&gt;) 将日期时间指定为自 Unix 纪元(1970 年 1 月 1 日)以来的毫秒数,并返回生成的 ISODate 实例。

      更重要的是,在内部,日期对象存储为带符号的 64 位整数,表示自 Unix 纪元(1970 年 1 月 1 日)以来的毫秒数。

      【讨论】:

      • 这个答案的问题是,当谈到生日时,你永远不希望结果是“在客户的本地时区”。如果一个人出生于 7 月 3 日,而您在 7 月 3 日将其存储为 UTC+0,则对于将导致不同本地日期的语言环境。
      【解决方案4】:

      我也在寻找这个问题的最佳解决方案,在阅读这些答案时,我认为最简单的解决方案会忽略时间,从而忽略时区变化,但仍然允许对人的年龄等进行比较和查询。沿 YYYYMMDD 行使用整数格式。

      因此对于 1980 年 3 月 12 日的出生日期,这将保存为整数 19800312。

      然后我找到了这个适用于 Mongoose 的插件,它或多或少地做了:https://github.com/boblauer/mongoose-dateonly

      唯一的缺点是,如果您想使用聚合框架,则必须直接使用 DateOnly。

      【讨论】:

        【解决方案5】:

        这是一个有趣的问题,不能轻易回答。正如@Andrey Degtyaruk 已经注意到的那样,这完全与这些数据的目的有关。

        就我而言,我几乎解决了类似的问题:

        store time like a YYYYMMDD string
        

        但是,有点不同。因为“时间戳”字段已被 MongoDB (according to BSON docs) 保留,我将日期转换为时间戳 (you could use one of these js scripts if you're interested) 并将其作为“lastModified”:“数字”存储在数据库中。

        我不确定我的方法是否与您的出生日期案例相关,但它仍然是一种方法,您可以尝试一下。

        【讨论】:

          【解决方案6】:

          正如 cmets 中所述,它几乎取决于您的最终目标。我建议您使用 MongoDate,因为它是 MongoDB 中日期的本机格式,并且可以让其他开发人员保持直观。 本机类型支持一系列开箱即用的有用方法,例如,您可以在 map-reduce 作业中使用这些方法。

          另外,出生日期“1990-05-21”存储为“1990-05-20T23:00:00Z”(前一天)

          我认为这只是因为您服务器上的时区是 UTC+1。您可以在保存到数据库之前手动将时区设置为 UTC,它会解决您的问题。

          【讨论】:

          • “这取决于你的最终目标”是什么意思?我的目标是保存出生日期并使用它进行任何类型的查询(就像所有其他值一样)。为了节省时间和出生日期,这听起来有点奇怪。在我的身份证上,除了出生日期之外,我没有时间。所有那些根本不需要时间的价值观都会发生这种情况。保存前将 UTC 设置为零,这意味着将时间设置为午夜,而不是“空”。这对我来说是无稽之谈。
          • > 我的目标是保存出生日期并使用它进行任何类型的查询(就像所有其他值一样)这取决于您要执行哪种查询。例如,如果您想查询生日在星期五的所有用户,则很难用字符串实现。以及除完全匹配之外的所有其他特定于日期的查询。如果使用字符串,您将如何执行查询以选择出生于 21.03.1979 和 22.02.1980 之间的所有用户?
          • 对于“各种查询”,我的意思是没有限制。发票也是如此:我是否存储带有午夜时间的发票?我不知道我会怎么做,这就是我问的原因。对我来说,MongoDB 没有简单的“日期”类型似乎很荒谬。
          • 你为什么觉得这很荒谬?简单地说 - 不要在结果中使用除日期之外的任何内容。忽略时间和时区,你就完成了。我在这里根本看不到任何问题。 docs.mongodb.com/v3.2/reference/bson-types/…
          • 感谢您的回答。我认为存储我不会使用的无意义时间是“形式上”的荒谬。我们正在讨论使用格林威治午夜的 UTC+0 存储日期。它既不是字节的事实(我不在乎),但所有数据库都有一个“日期”类型,因为有很多值没有时间:出生/死亡日期,发票,食物过期,考试......
          猜你喜欢
          • 1970-01-01
          • 2016-12-22
          • 2013-06-14
          • 1970-01-01
          • 2011-04-16
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多