Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mongodb aggregate: convert date to another timezone

I save my transaction with something like :

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

each of transaction has timestamp field under UTC timezone in it. Since I live in Jakarta (UTC+7) timezone, I need to add 7 hours to my timestamp before aggregation. Here's my mongo syntax:

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

It returns:

    {
        "_id" : ObjectId("56a01ed143f2fd071793d63b"),
        "year" : 2016,
        "month" : 1,
        "day" : 20
    },
    {
        "_id" : ObjectId("56a01ed143f2fd071793d63b"),
        "year" : 2016,
        "month" : 1,
        "day" : 20
    }

which is wrong since the first transaction (code A), is happened at 21st January, but since it was converted to UTC (-7 Hours), it became ISODate("2016-01-20T23:57:05.771Z")

Note: I'm aware about the same problem over here, here's what I've been tried so far:

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

but it returns can't convert from BSON type NumberDouble to Date error. Any suggestions?

like image 326
DennyHiu Avatar asked Jan 21 '16 03:01

DennyHiu


People also ask

How do I change the Date format in aggregation in MongoDB?

If you have documents that store dates as Date objects, but you want to return them in a different format, you can use the $dateToString aggregate pipeline operator. The $dateToString operator converts the Date object to a string, and optionally allows you to specify a format for the resulting output.

Does MongoDB convert Date to UTC?

MongoDB stores times in UTC by default, and will convert any local time representations into this form. Applications that must operate or report on some unmodified local time value may store the time zone alongside the UTC timestamp, and compute the original local time in their application logic.

What is $EXPR in MongoDB?

$expr can build query expressions that compare fields from the same document in a $match stage. If the $match stage is part of a $lookup stage, $expr can compare fields using let variables. See Perform Multiple Joins and a Correlated Subquery with $lookup for an example.

What is $project in MongoDB?

Definition. $project. Passes along the documents with the requested fields to the next stage in the pipeline. The specified fields can be existing fields from the input documents or newly computed fields.

How to store the current UTC date and time in MongoDB?

For example, the following code stores the current UTC date and time into MongoDB: Always use datetime.datetime.utcnow (), which returns the current time in UTC, instead of datetime.datetime.now (), which returns the current local time. Avoid doing this:

How to convert datetime datetime to local time in pymongo?

By setting the tz_aware option on CodecOptions, datetime.datetime objects will be timezone-aware and have a tzinfo property that reflects the UTC timezone. PyMongo 3.1 introduced a tzinfo property that can be set on CodecOptions to convert datetime.datetime objects to local time automatically.

How to add timestamp in $project stage in MongoDB?

We can add the "timestamp" to 7 * 60 * 60 * 1000 in a $project stage. The following pipeline seems to work in MongoDB 3.4 or older.

How does MongoDB handle the DST offset for Olson timezone identifiers?

When using an Olson Timezone Identifier in the <timezone> field, MongoDB applies the DST offset if applicable for the specified timezone. For example, consider a sales collection with the following document: The following aggregation illustrates how MongoDB handles the DST offset for the Olson Timezone Identifier.


1 Answers

As an update, MongoDB 3.6 has a new timezone parameter for date manipulation in the aggregation framework. Most date-related operators accept this optional parameter, see $hour for one example.

For example, if we have a document where the date is exactly the new year in UTC:

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

We can display the date in New York timezone:

> 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 }

We can also display the date in Sydney timezone:

> 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 }

The timezone description is using the standard Olson Timezone Identifier string.

like image 63
kevinadi Avatar answered Oct 24 '22 16:10

kevinadi