我的收藏文档中有一个 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-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();
读取每个文档以获取“日期”值并进行相应调整,然后将更新后的日期值发送回文档。
关于mongodb - 如何更新 ISO 日期的收集和增量时间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31760736/