我的收藏文件中有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();
答案 0 :(得分:2)
默认情况下,MongoDB将所有DateTime存储为UTC。
有两种方法可以做到这一点:
应用方(推荐)
从数据库中提取start
和end
时,请使用您选择的语言将其从UTC更改为本地日期时间。
要查看Python中的一个好例子,请查看this answer
数据库方面(不推荐)
另一种选择是编写一个mongodb查询,它会像您最初想要的那样为start
和end
增加8小时。然而,这会将时间设置为UTC,但将来会设置为8小时,对于其他开发人员和解析应用程序端时则变得不合逻辑。
这需要根据文档中的其他值进行更新,因此您必须以described here的形式遍历每个文档。
答案 1 :(得分:2)
我全心全意地与Ewan提供的答案进行协商,因为您确实应该将所有时间保留在UTC的数据库中。所有的情绪都是正确的。只是通过实际例子真正增加了这一点。
作为一个工作示例,我们假设我有两个人使用这些数据,一个在纽约,另一个在悉尼,分别是UTC-5
和UTC+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();
阅读每个文档以获得" date"值并相应地调整并将更新的日期值发送回文档。