MongoDB $isoWeekYear

In MongoDB, the $isoWeekYear aggregation pipeline operator returns the ISO week-numbering year for a given date value. This is the year number in ISO 8601 format.

When using the $isoWeekYear operator, you can optionally specify a timezone to use for the result.

The $isoWeekYear 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 year from the born field in that document.

db.cats.aggregate(
  [
    {
      $project:
        {
          _id: 0,
          birthIsoWeekYear: { $isoWeekYear: "$born" }
        }
    }
  ]
)

Result:

{ "birthIsoWeekYear" : NumberLong(2020) } 

We can see that the ISO year is actually 2020, even though the date specifies 2021. This is because the ISO year doesn’t finish until the last week finishes. And in this case, the week started at the end of the previous year, and has yet to finish. This is how ISO years work.

Here, I used birthIsoWeekYear as the field name to return, but this could have been anything (such as isoWeekYear, isoYear, 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 $isoWeekYear operator.

When you do this, the argument passed to $isoWeekYear 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 year in two different timezones, each using the Olson timezone IDs:

db.cats.aggregate(
  [
    {
      $project: {
          _id: 0,
          honolulu: { 
            $isoWeekYear: { date: "$born", timezone: "Pacific/Honolulu" }
            },
          auckland: { 
            $isoWeekYear: { date: "$born", timezone: "Pacific/Auckland" }
            }
        }
    }
  ]
)

Result:

{ "honolulu" : NumberLong(2020), "auckland" : NumberLong(2021) } 

In this case, the date moves forward to the next ISO year 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": { 
            $isoWeekYear: { date: "$born", timezone: "-1000" }
            },
          "utcOffset+1200": { 
            $isoWeekYear: { date: "$born", timezone: "+1200" }
            }
        }
    }
  ]
)

Result:

{ "utcOffset-1000" : NumberLong(2020), "utcOffset+1200" : NumberLong(2021) } 

Return the ISO Year from an ObjectId

You can use $isoWeekYear to return the ISO year 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 $isoWeekYear to return the ISO year 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"},
          "isoWeekYear": { $isoWeekYear: "$_id" }
        }
    }
  ]
).pretty()

Result:

{
	"_id" : ObjectId("6008c9a5c8eb4369cf6ad9cc"),
	"timeStamp" : ISODate("2021-01-21T00:24:05Z"),
	"isoWeekYear" : NumberLong(2021)
}

We can see that the document was created in the ISO year 2021.

In this case, I also used the $toDate aggregation pipeline operator to return the timestamp portion of the ObjectId.

About the ISO Week Date System

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.