mongodb - 如何更新 ISO 日期的收集和增量时间

标签 mongodb

我的收藏文档中有一个 ISO 日期。

"start" : ISODate("2015-07-25T17:35:00Z"),
"end" : ISODate("2015-09-01T23:59:00Z"),

目前它们处于 GMT +0,我需要它们处于 GMT +8。因此我需要在现有字段上添加 8 小时。我如何通过 mongodb 查询来做到这一点?

感谢您的建议。

更新的代码片段

var offset = 8,
bulk = db.collection.initializeUnorderedBulkOp(),
count = 0;

db.collection.find().forEach(doc) {
bulk.find({ "_id": doc._id }).updateOne({
   "$set": { “startDateTime": new Date(
       doc.startDateTime.valueOf() + ( 1000 * 60 * 60 * offset )
   ) }
});
count++;

if ( count % 1000 == 0 ) {
    bulk.execute();
    bulk = db.collection.initializeUnorderedBulkOp();
}
});

if ( count % 1000 !=0 )
    bulk.execute();

最佳答案

我完全同意Ewan提供的答案在这里,您确实应该将所有时间保存在 UTC 数据库中。所有的情绪都是正确的。只是通过实际例子来真正补充这一点。

作为一个工作示例,假设我有两个人使用该数据,一个在纽约,一个在悉尼,分别为 UTC-5UTC+10 。现在考虑以下数据:

{ "date": ISODate("2015-08-01T04:40:03.389Z") }

据此,这是实际“事件”发生的时间。对于悉尼用户来说,该事件发生在 8 月 1 日一整天,而对于纽约用户来说,该事件仍然发生在 7 月 31 日。

但是,如果我按如下方式构建悉尼的“本地化”时间,则 UTC 考虑因素仍然是正确的:

 new Date("2015/08/01")
 ISODate("2015-07-31T14:00:00Z")

这会通过从本地时区转换为 UTC 来强制执行时差。因此,本地化日期将选择 UTC 格式的正确值。因此,悉尼用户对 8 月 1 日开始的看法包括从 7 月 31 日下午 2 点开始的所有时间,并类似地调整为范围选择的结束日期。对于 UTC 数据,客户端的这一断言是正确的,并且从他们的角度来看,所选数据在预期范围内。

如果您要“汇总”给定日期的结果,则可以将“时间差”数学构建到表达式中。因此对于 UTC+10 你会这样做:

var offset = 10;

db.collection.aggregate([
    { "$group": {
        "_id": {
            "$subtract": [
                { "$add": [
                    {"$subtract": [ "$date", new Date(0)]},
                    offset * 1000 * 60 * 60 
                ]},
                { "$mod": [
                    { "$add": [ 
                        { "$subtract": [ "$date", new Date(0) ] },
                        offset * 1000 * 60 * 60
                    ]},
                    1000 * 60 * 60 * 24
                ]}
            ]
        },
        "count": { "$sum": 1 }
   }}

然后,当向正在查看数据的客户端报告“日期”时,会考虑区域设置的“偏移量”。因此,在“调整日期”发生的任何导致不同日期(例如 8 月 31 日)的事件都将通过此调整汇总到正确的分组中。

因为您的数据很可能会从不同时区的人们的角度使用,这正是您应该以 UTC 格式保存日期数据的原因。客户将完成这项工作,或者您可以根据需要进行相应调整。

简而言之:

  • 客户端:以本地时间构造,以UTC发送

  • 服务器:提供 TZ 偏移并在返回时从 UTC 调整为本地

将日期保留为现有的正确格式,并使用此处描述的方法来报告它们。

<小时/>

但是如果你犯了一个错误

但是,如果您在构建数据时犯了错误,并且所有时间实际上都是“本地”时间,但表示为 UTC,即:

ISODate("2015-08-01T11:10:43.569Z") // actually meant to be 11am in UTC+10 :(

它应该在哪里:

ISODate("2015-08-01T01:10:43.569Z") // This is 11am UTC+10 :)

然后您将按如下方式更正此问题:

var offset = 10,
    bulk = db.collection.initializeUnorderedBulkOp(),
    count = 0;

db.collection.find().forEach(doc) {
    bulk.find({ "_id": doc._id }).updateOne({
       "$set": { "date": new Date(
           doc.date.valueOf() - ( 1000 * 60 * 60 * offset )
       ) }
    });
    count++;

    if ( count % 1000 == 0 ) {
        bulk.execute();
        bulk = db.collection.initializeUnorderedBulkOp();
    }
});

if ( count % 1000 !=0 )
    bulk.execute();

读取每个文档以获取“日期”值并进行相应调整,然后将更新后的日期值发送回文档。

关于mongodb - 如何更新 ISO 日期的收集和增量时间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31760736/

相关文章:

java - 当不再需要 DBCursor 时,我应该在方法中关闭它,还是可以将其留给垃圾收集器?

asp.net - 使用 HttpClient 进行测试时,Task.Run 永远不会完成

javascript - 如何使用模式在 Javascript 中创建默认对象?

spring - MongoDB GridFS 身份验证不起作用

mongodb - 有没有办法在 mongoDB 中索引一个文档来填充它的引用?

angularjs - 需要在mongodb中执行push操作不行

node.js - MongoDB API 分页

Mongodb 因地址无效访问而崩溃 - 段错误信号 11 - 版本 2.6

java - Netty 和 MongoDB 异步回调不能一起工作

node.js - 无法在 Ubuntu 18.04 Bionic 上安装/删除 mongodb-org - "mongodb-org-tools : Depends: mongodb-database-tools but it is not installed"