In MongoDB, the $dateFromParts
aggregation pipeline operator constructs and returns a Date object from the date’s constituent parts.
You provide each date part as a separate field.
You can specify your constituent date fields in ISO week date format if required.
Example
Suppose we have a collection called dateParts
with the following document:
{ "_id" : 1, "year" : 2020, "month" : 12, "day" : 31, "hour" : 23, "minute" : 30, "second" : 25, "millisecond" : 123 }
The document contains a different field for each date part.
We can run the following code to return a date object from the fields in those documents.
db.dateParts.aggregate([
{
$project: {
date: {
$dateFromParts: {
"year": "$year",
"month": "$month",
"day": "$day",
"hour": "$hour",
"minute": "$minute",
"second": "$second",
"millisecond": "$millisecond"
}
}
}
}])
Result:
{ "_id" : 1, "date" : ISODate("2020-12-31T23:30:25.123Z") }
All date/time parts have been converted to a single date object.
Timezones
You can use the timezone
field to specify a timezone.
The timezone can be specified using either the Olson timezone identifier (e.g. "Europe/London"
, "GMT"
) or the UTC offset (e.g. "+02:30"
, "-1030"
).
Olson Timezone Identifier
Here’s an example that uses Olson timezone IDs to output three different dates from a single document, based on three different timezones.
db.dateParts.aggregate([
{
$project: {
dateUTC: {
$dateFromParts: {
"year": "$year",
"month": "$month",
"day": "$day",
"hour": "$hour",
"minute": "$minute",
"second": "$second",
"millisecond": "$millisecond",
"timezone": "Pacific/Auckland"
}
},
dateHonolulu: {
$dateFromParts: {
"year": "$year",
"month": "$month",
"day": "$day",
"hour": "$hour",
"minute": "$minute",
"second": "$second",
"millisecond": "$millisecond",
"timezone": "Pacific/Honolulu"
}
},
dateAuckland: {
$dateFromParts: {
"year": "$year",
"month": "$month",
"day": "$day",
"hour": "$hour",
"minute": "$minute",
"second": "$second",
"millisecond": "$millisecond",
"timezone": "Pacific/Auckland"
}
}
}
}]).pretty()
Result:
{ "_id" : 1, "dateUTC" : ISODate("2020-12-31T10:30:25.123Z"), "dateHonolulu" : ISODate("2021-01-01T09:30:25.123Z"), "dateAuckland" : ISODate("2020-12-31T10:30:25.123Z") }
UTC Offset
Here’s an example that uses the UTC offset.
db.dateParts.aggregate([
{
$project: {
"date+00:00": {
$dateFromParts: {
"year": "$year",
"month": "$month",
"day": "$day",
"hour": "$hour",
"minute": "$minute",
"second": "$second",
"millisecond": "$millisecond",
"timezone": "+00:00"
}
},
"date-10:00": {
$dateFromParts: {
"year": "$year",
"month": "$month",
"day": "$day",
"hour": "$hour",
"minute": "$minute",
"second": "$second",
"millisecond": "$millisecond",
"timezone": "-10:00"
}
},
"date+12:00": {
$dateFromParts: {
"year": "$year",
"month": "$month",
"day": "$day",
"hour": "$hour",
"minute": "$minute",
"second": "$second",
"millisecond": "$millisecond",
"timezone": "+12:00"
}
}
}
}]).pretty()
Result:
{ "_id" : 1, "date+00:00" : ISODate("2020-12-31T23:30:25.123Z"), "date-10:00" : ISODate("2021-01-01T09:30:25.123Z"), "date+12:00" : ISODate("2020-12-31T11:30:25.123Z") }
ISO Week Date Format
The date parts can be specified using the ISO 8601 format if required.
In particular, you can use:
Format Specifier | Output |
---|---|
isoWeekYear | Year in ISO 8601 format. This field is required if not using year (and year is required if not using isoWeekYear ). |
isoWeek | Week of the year in ISO 8601 format. Can only be used with isoWeekYear . |
isoDayOfWeek | Day of week (1-Monday, 7-Sunday). Can only be used with isoWeekYear . |
Suppose we insert a second document that looks like this:
{ "_id" : 2, "isoWeekYear" : 2021, "isoWeek" : 32, "isoDayOfWeek" : 7, "hour" : 23, "minute" : 30, "second" : 25, "millisecond" : 123, "timezone" : "UTC" }
We can see that it uses isoWeekYear
, isoWeek
, and isoDayOfWeek
instead of year
, month
, and day
(which is what the first document uses).
We can use the following code to construct a Date object from this document:
db.dateParts.aggregate([
{ $match: { _id: 2} },
{
$project: {
date: {
$dateFromParts: {
"isoWeekYear": "$isoWeekYear",
"isoWeek": "$isoWeek",
"isoDayOfWeek": "$isoDayOfWeek",
"hour": "$hour",
"minute": "$minute",
"second": "$second",
"millisecond": "$millisecond",
"timezone": "$timezone"
}
}
}
}
])
Result:
{ "_id" : 2, "date" : ISODate("2021-08-15T23:30:25.123Z") }
Out of Range Fields
Starting in MongoDB 4.4, the supported value range for year
and isoWeekYear
is 1-9999
. In prior versions, the lower bound for these values was 0
and the supported value range was 0-9999
.
Starting in MongoDB 4.0, if the value specified for fields other than year
, isoWeekYear
, and timezone
is outside the valid range, the $dateFromParts
operator carries or subtracts the difference from other date parts to calculate the date.
Values Higher than the Range
Suppose we add the following document to our collection:
{ "_id" : 3, "year" : 2020, "month" : 14, "day" : 65, "hour" : 48, "minute" : 130, "second" : 625, "millisecond" : 123 }
Many of the date and time fields in this document are higher than their respective valid ranges.
Let’s run the following command to convert it into a Date object:
db.dateParts.aggregate([
{ $match: { _id: 3} },
{
$project: {
date: {
$dateFromParts: {
"year": "$year",
"month": "$month",
"day": "$day",
"hour": "$hour",
"minute": "$minute",
"second": "$second",
"millisecond": "$millisecond"
}
}
}
}
])
Result:
{ "_id" : 3, "date" : ISODate("2021-04-08T02:20:25.123Z") }
We can see that the date parts in the resulting Date object are different to their respective date parts in the document. This is because $dateFromParts
recalculated the date to account for the date part values that exceeded their normal range.
Values Lower than the Range
Suppose we add the following document to our collection:
{ "_id" : 4, "year" : 2020, "month" : 0, "day" : 0, "hour" : 0, "minute" : 0, "second" : 0, "millisecond" : 0 }
Many of the date and time fields in this document are lower than their respective valid ranges.
Let’s run the following command to convert it into a Date object:
db.dateParts.aggregate([
{ $match: { _id: 4} },
{
$project: {
date: {
$dateFromParts: {
"year": "$year",
"month": "$month",
"day": "$day",
"hour": "$hour",
"minute": "$minute",
"second": "$second",
"millisecond": "$millisecond"
}
}
}
}
])
Result:
{ "_id" : 4, "date" : ISODate("2019-11-30T00:00:00Z") }