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?
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.
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.
$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.
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.
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:
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.
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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With