In MongoDB, the $isoWeek
aggregation pipeline operator returns the week number in ISO 8601 format, ranging from 1
to 53
.
When using the $isoWeek
operator, you can optionally specify a timezone to use for the result.
The $isoWeek
operator accepts either a date (as either a Date, a Timestamp, or an ObjectId), or a document that specifies the date and timezone to use.
Example
Suppose we have a collection called cats
with the following document:
{ "_id" : ObjectId("6008c9a5c8eb4369cf6ad9cc"), "name" : "Scratch", "born" : ISODate("2021-01-03T23:30:15.123Z") }
We can run the following code to extract the ISO week from the born
field in that document.
db.cats.aggregate(
[
{
$project:
{
_id: 0,
birthIsoWeek: { $isoWeek: "$born" }
}
}
]
)
Result:
{ "birthIsoWeek" : 53 }
We can see that the ISO week is actually 53, even though the date is in January. This is because the week started at the end of the previous year, and has yet to finish. This is how ISO weeks work.
Here, I used birthIsoWeek
as the field name to return, but this could have been anything (such as isoWeek
, week
, etc).
The _id
field is returned by default when using projections in MongoDB, but in this example I explicitly hid the _id
field using _id: 0
.
Specify a Timezone
You can specify a timezone to use for the output of the $isoWeek
operator.
When you do this, the argument passed to $isoWeek
must be of the following form:
{ date: <dateExpression>, timezone: <tzExpression> }
Where <dateExpression>
is the date to use, and <tzExpression>
is the timezone to use.
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 outputs the ISO week in two different timezones, each using the Olson timezone IDs:
db.cats.aggregate(
[
{
$project: {
_id: 0,
honolulu: {
$isoWeek: { date: "$born", timezone: "Pacific/Honolulu" }
},
auckland: {
$isoWeek: { date: "$born", timezone: "Pacific/Auckland" }
}
}
}
]
)
Result:
{ "honolulu" : 53, "auckland" : 1 }
In this case, the date moves forward to the next ISO week when using the Pacific/Auckland
timezone.
UTC Offset
Here’s the same example, except this time we use the UTC offset.
db.cats.aggregate(
[
{
$project: {
_id: 0,
"utcOffset-1000": {
$isoWeek: { date: "$born", timezone: "-1000" }
},
"utcOffset+1200": {
$isoWeek: { date: "$born", timezone: "+1200" }
}
}
}
]
)
Result:
{ "utcOffset-1000" : 53, "utcOffset+1200" : 1 }
Return the ISO Week from an ObjectId
You can use $isoWeek
to return the ISO week portion from an ObjectId.
ObjectId values are 12 byte hexadecimal values that consist of:
- A 4 byte timestamp value, representing the ObjectId’s creation, measured in seconds since the Unix epoch.
- A 5 byte is a random value
- A 3 byte incrementing counter, initialised to a random value.
To recap, our document looks like this:
{ "_id" : ObjectId("6008c9a5c8eb4369cf6ad9cc"), "name" : "Scratch", "born" : ISODate("2021-01-03T23:30:15.123Z") }
This document contains an ObjectId. We can therefore use $isoWeek
to return the ISO week that our document was created (or more specifically, when the _id
field’s ObjectId value was created).
Example:
db.cats.aggregate(
[
{
$project:
{
"timeStamp": { $toDate: "$_id"},
"isoWeek": { $isoWeek: "$_id" }
}
}
]
).pretty()
Result:
{ "_id" : ObjectId("6008c9a5c8eb4369cf6ad9cc"), "timeStamp" : ISODate("2021-01-21T00:24:05Z"), "isoWeek" : 3 }
We can see that the document was created on the 3rd week of the year when using the ISO 8601 format.
In this case, I also used the $toDate
aggregation pipeline operator to return the timestamp portion of the ObjectId.
What is an ISO Week?
The ISO week date system is a calendar system that is part of the ISO 8601 date and time standard issued by the International Organization for Standardization (ISO). The system specifies a week year on top of the Gregorian calendar by defining a notation for ordinal weeks of the year.
ISO week-numbering years have either 52 or 53 full weeks. This means that there are either 364 or 371 days in the year, instead of the usual 365 or 366 days.
ISO weeks start with Monday. Each ISO week’s year is the Gregorian year in which the Thursday falls. ISO week numbers start at 1
with the week that contains the year’s first Thursday.