Reputation: 6110
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?
Upvotes: 19
Views: 38810
Reputation: 120
You can use the $dateToString
method with $project to get specified timezone result.
Note this requires a format argument, see Format Specifiers for more info.
$project:{
created_at: {
$dateToString: {
date: '$createdAt',
timezone: '+07:00',
format: '%d-%m-%Y %H:%M'
}
}
}
Upvotes: 7
Reputation: 13795
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 }
Or could use a single $dateToParts
> db.test.aggregate([
{$project:{
dateToParts:{$dateToParts:{date:'$dt',timezone:'Australia/Sydney'}}
}}
])
{ "_id": 1, "dateToParts": { "day": 1, "hour": 11, "millisecond": 0, "minute": 0, "month": 1, "second": 0, "year": 2018 } }
The timezone description is using the standard Olson Timezone Identifier string.
Upvotes: 42
Reputation: 11
You need to add the name of the timezone like so:
$project: {
releaseDate: {
$dateToString: {
date: "$releaseDate",
timezone: "America/Sao_Paulo",
format: "%d/%m/%Y %H:%M:%S"
}
}
}
Upvotes: 1
Reputation: 21
Hi sharing my solution used on one of my extracts using mongodb version 3.4 or below and need it to covert from utc to manila time +08:00
see the sample query below
db.collection.aggregate([
{$project:{
"created_at":{"$dateToString": { "date":{ "$add": [ "$yourtimestampfield", 8 * 60 * 60 * 1000 ] }, "format": "%Y-%m-%d %H:%M:%S"}},
}}])
Upvotes: 2
Reputation: 61253
MongoDB 3.6 added timezone parameter to the date manipulation operators. See Kevin's answer.
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.
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 ] } }
} }
])
Upvotes: 9