Mongodb聚合:将日期转换为另一个时区

Den*_*Hiu 8 datetime date mongodb aggregation-framework

我保存我的交易,例如:

{code: "A", total: 250000, timestamp: ISODate("2016-01-20T23:57:05.771Z")},
{code: "B", total: 300000, timestamp: ISODate("2016-01-20T05:57:05.771Z")}
Run Code Online (Sandbox Code Playgroud)

每个事务都有timestampUTC时区下的字段.由于我住在雅加达(UTC + 7)时区,我需要在聚合之前将7小时添加到我的时间戳.这是我的mongo语法:

db.transaction.aggregate(
[
 {
   $project:
     {
       year: { $year: "$timestamp" },
       month: { $month: "$timestamp" },
       day: { $dayOfMonth: "$timestamp" }
     }
 }
])
Run Code Online (Sandbox Code Playgroud)

它返回:

    {
        "_id" : ObjectId("56a01ed143f2fd071793d63b"),
        "year" : 2016,
        "month" : 1,
        "day" : 20
    },
    {
        "_id" : ObjectId("56a01ed143f2fd071793d63b"),
        "year" : 2016,
        "month" : 1,
        "day" : 20
    }
Run Code Online (Sandbox Code Playgroud)

这是错误的,因为第一次交易(代码A)发生在1月21日,但由于它被转换为UTC(-7小时),它变成了ISODate("2016-01-20T23:57:05.771Z")

注意:我在这里也知道同样的问题,这是我到目前为止所尝试过的:

db.transaction.aggregate(
[
 {$project: {"timestamp": {$add: [7 * 60 * 60 * 1000]}}},
 {
   $project:
     {
       year: { $year: "$timestamp" },
       month: { $month: "$timestamp" },
       day: { $dayOfMonth: "$timestamp" }
     }
 }
])
Run Code Online (Sandbox Code Playgroud)

但它返回can't convert from BSON type NumberDouble to Date错误.有什么建议?

kev*_*adi 19

作为更新,MongoDB 3.6在聚合框架中具有用于日期操作的新时区参数.大多数与日期相关的运算符接受此可选参数,请参阅$ hour作为示例.

例如,如果我们有一个文档,其中日期恰好是UTC的新年份:

> db.test.find()
{"_id": 1, "dt": ISODate("2018-01-01T00:00:00Z")}
Run Code Online (Sandbox Code Playgroud)

我们可以在纽约时区显示日期:

> db.test.aggregate([
...     {$project:{
...         date:{$dayOfMonth:{date:'$dt',timezone:'America/New_York'}},
...         month:{$month:{date:'$dt',timezone:'America/New_York'}},
...         year:{$year:{date:'$dt',timezone:'America/New_York'}},
...         hour:{$hour:{date:'$dt',timezone:'America/New_York'}}
...     }}
... ])
{ "_id": 1, "date": 31, "month": 12, "year": 2017, "hour": 19 }
Run Code Online (Sandbox Code Playgroud)

我们还可以在悉尼时区显示日期:

> db.test.aggregate([
...     {$project:{
...         date:{$dayOfMonth:{date:'$dt',timezone:'Australia/Sydney'}},
...         month:{$month:{date:'$dt',timezone:'Australia/Sydney'}},
...         year:{$year:{date:'$dt',timezone:'Australia/Sydney'}},
...         hour:{$hour:{date:'$dt',timezone:'Australia/Sydney'}}
...     }}
... ])
{ "_id": 1, "date": 1, "month": 1, "year": 2018, "hour": 11 }
Run Code Online (Sandbox Code Playgroud)

时区描述使用标准的Olson时区标识符字符串.


sty*_*ane 7

您需要添加"时间戳",7 * 60 * 60 * 1000您也可以在一个$project阶段中执行此操作.

db.collection.aggregate([
    { "$project": {
        "year": { "$year": { "$add": [ "$timestamp", 7 * 60 * 60 * 1000 ] } }, 
        "month": { "$month": { "$add": [ "$timestamp", 7 * 60 * 60 * 1000 ] } }, 
        "day": { "$dayOfMonth": { "$add": [ "$timestamp", 7 * 60 * 60 * 1000 ] } } 
    } }
])
Run Code Online (Sandbox Code Playgroud)

哪个回报:

{
        "_id" : ObjectId("56a07f8f8448ed9fd2359365"),
        "year" : 2016,
        "month" : 1,
        "day" : 21
}
{
        "_id" : ObjectId("56a07f8f8448ed9fd2359366"),
        "year" : 2016,
        "month" : 1,
        "day" : 20
}
Run Code Online (Sandbox Code Playgroud)

  • MongoDB 3.6 现在支持此功能,请参阅 @Kevin 的回答。 (2认同)

Pra*_*ina 6

您可以使用$dateToString$project 的方法来获取指定时区的结果。

请注意,这需要格式参数,请参阅格式说明符以获取更多信息。

$project:{
     created_at: {
            $dateToString: {
              date: '$createdAt',
              timezone: '+07:00',
              format: '%d-%m-%Y %H:%M'
          }
     }
 }
Run Code Online (Sandbox Code Playgroud)