MongoDB $isoWeek

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.