如何为ISO日期更新收款和增加小时数 [英] How to update collection and increment hours for ISO date

查看:56
本文介绍了如何为ISO日期更新收款和增加小时数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的收款文件中有一个ISO日期.

I have an ISO date in my collection documents.

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

当前它们处于格林尼治标准时间+0,我需要它们为格林尼治标准时间+8.因此,我需要在现有字段中增加8个小时.如何通过mongodb查询做到这一点?

Currently they are in GMT +0, i need them to be GMT +8. Therefore i need to add 8 hours to the existing field. How do i do this via a mongodb query?

建议受到赞赏.

更新的代码段

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数据库中.那里的所有观点都是正确的.仅通过实际示例真正添加到这一点.

I aggree wholeheartedly with the answer provided by Ewan here in that you really should keep all times in a database in UTC. And all the sentiments are correct there. Only really adding to this with practical examples.

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

As a working example, Let's say I have two people using the data, one in New York and one in Sydney, being UTC-5 and UTC+10 respectively. Now consider the following data:

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

基于此,这是实际的事件"发生的时间.从悉尼用户的角度来看,该事件全天发生在8月1日,而对于纽约的人来说,该事件仍在7月31日发生.

Based on that, this is the time the actual "event" takes place. To the perspective of the user in Sydney the event takes place on the 1st August as a whole day where as to the person in New York it is still occuring on the 31st July.

但是,如果我按照以下方式为悉尼构建一个本地化"时间,那么UTC的考虑仍然是正确的:

If however I construct a "localized" time for Sydney as follows, the UTC consideration is still correct:

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

这通过从本地时区转换为UTC来强制时差.因此,本地化日期将选择UTC中的正确值.因此,预计8月1日开始的悉尼用户包括从7月31日下午2点开始的所有时间,并且类似地调整为范围选择的结束日期.对于UTC中的数据,来自客户端的此声明正确无误,并且从他们的角度来看,所选数据在预期范围内.

This enforces the time difference like it should by converting from the local timezone to UTC. Therefore a localized date will select the correct values in UTC. So the Sydney user perpective of the start of the 1st August includes all times from 2pm on 31st July and similarly adjusted to the end date of a range selection. With data in UTC, this assertion from the client end it correct, and to their perpective the selected data was in the expected range.

如果您要汇总"给定日期的结果,则可以在表达式中构建时差"数学.因此,对于UTC + 10,您可以这样做:

In the case where you were "aggregating" results for a given day, then you build in the "time difference" math into the expression. So for UTC+10 you would do:

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日这样的不同日期,都将通过此调整汇总到正确的分组中.

Which then takes the "offset" for the locale in consideration when reporting back the "dates" to the perpective of the client that was viewing the data. So anything that occurred on an "Adjusted date" resulting in a different day such as the 31st August would be aggregated into the correct grouping by this adjustment.

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

Because your data may very well be used from the perpective of people in different timezones is exactly the reason why you should keep data for dates in UTC format. The client will do the work, or you can adjust accordingly where needed.

简而言之:

  • 客户端:在当地时间构建,以UTC发送

  • Client: Construct in local time, send in UTC

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

Server: Provide TZ Offset and adjust from UTC to local on return

以正确的日期格式保存日期,并使用此处介绍的方法进行报告.

Leave your dates in the correct format they are already in and use the methods described here to report on them.

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

If however you made a mistake in contruction of your data and all times are actually "local" times but repesented as UTC, ie:

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 :)

然后您将按以下步骤更正此问题:

Then you would correct this as follows:

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();

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

Reading each document to get the "date" value and adjusting that accordingly and sending the updated date value back to the document.

这篇关于如何为ISO日期更新收款和增加小时数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆