如何更新集合并增加ISO日期的小时数
如何更新集合并增加ISO日期的小时数
我在我的文档集合中有一个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();
如何更新集合并为ISO日期增加小时
有时候,在处理数据库中的时间时,我们需要考虑不同时区的情况。通常,我们会将所有时间都存储为UTC时间,并在需要时根据具体时区进行转换。这样可以确保数据的一致性和准确性。下面是一种处理方式。
假设有两个人使用数据,一个在纽约,一个在悉尼,分别处于UTC-5和UTC+10时区。现在考虑以下数据:
{ "date": ISODate("2015-08-01T04:40:03.389Z") }
根据这个数据,事件实际发生的时间是8月1日。对于悉尼的用户来说,事件是在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时间。
- 服务器:提供时区偏移量,并在返回时从UTC调整为本地时间。
保持数据的正确格式,并使用此处描述的方法进行报告。
但如果你犯了个错误
然而,如果在构建数据时犯了错误,所有时间实际上是“本地”时间,但表示为UTC时间,例如:
ISODate("2015-08-01T11:10:43.569Z") //实际上应该是UTC+10时区的上午11点 🙁
正确的应该是:
ISODate("2015-08-01T01:10:43.569Z") //这是UTC+10时区的上午11点 🙂
那么你可以按如下方式进行更正:
var offset = 10,
bulk = db.collection.initializeUnorderedBulkOp(),
count = 0;
db.collection.find().forEach(function(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();
通过读取每个文档并相应调整“date”值,将更新后的日期值发送回文档。
以上就是如何更新集合并为ISO日期增加小时的方法。