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