In ecommerce and marketing it’s relatively common to use ISO week numbers when reporting data. The ISO week system is a leap week calendar that forms part of the ISO 8601 date and time standard from the International Organization for Standardization or ISO.
The Gregorian calendar has a leap cycle that uses 97 leap days distributed across a 400-year period and contains a whole number 20871 weeks. This means the average year has 52.1775 weeks. By contrast, the ISO week number year, or ISO year, has either 52 or 53 full weeks, with 364 or 371 days, instead of the usual 365 or 366 in a Gregorian calendar year.
ISO weeks start on a Monday and end on a Sunday, which tends to be the common way that businesses measure their trading performance. In order to query databases or web analytics platforms to extract ecommerce or marketing data aligned to ISO weeks, you’ll need to be able to identify the start and end date for an ISO week, and work out the ISO week for a given date. Here’s how to do it in Python.
While you can calculate ISO week data manually, there’s a useful Python package called isoweek
that simplifies the calculations. Open a Jupyter notebook and enter the command below to install the isoweek
package.
!pip3 install isoweek
Requirement already satisfied: isoweek in /conda/envs/data-science-stack-2.5.1/lib/python3.7/site-packages (1.3.3)
Next, import the pandas
package and the Week
module from isoweek
.
import pandas as pd
from isoweek import Week
First, we’ll tackle how to calculate the ISO week for a given date by creating a function we can use in other projects. We’ll pass a date
string to this and use the Pandas to_datetime()
function to convert it to a datetime
object. Then we’ll use date.isocalendar()
and return the second value 1
from the list to obtain an integer containing the ISO week number.
def get_iso_week_from_date(date):
"""Return the ISO week from a date.
Args:
date (str): Date
Returns:
week (int): ISO week
"""
date = pd.to_datetime(date)
return date.isocalendar()[1]
week = get_iso_week_from_date('2022-02-28')
week
9
Next we’ll create a Python function to calculate the start date for a given ISO week using the year and the ISO week number. We’ll also add an optional argument for the date_format
so you can either return the date as a string or a datetime
object.
Since ISO weeks start on a Monday and end on a Sunday, we can calculate the start date for a given ISO week by passing the year
and week
arguments to Week()
and appending .monday()
to return that specific day. If we want the ISO week start date returned as a date string, i.e. YYYY-MM-DD
, then we can pass in the optional formatter, such as %Y-%m-%d
and we’ll get back the date in our chosen format.
def get_start_date_of_isoweek(year, week, date_format='datetime'):
"""
Get the start date of the given ISO week using isocalendar()
Args:
year (int): Year, i.e. 2022
week (int): Week, i.e. 34
date_format (string): Format of the returned date, default is datetime
Returns:
datetime.date: Start date of the given ISO week
"""
if date_format == 'datetime':
return Week(year, week).monday()
else:
return Week(year, week).monday().strftime(date_format)
start = get_start_date_of_isoweek(2022, 9)
start
datetime.date(2022, 2, 28)
end = get_start_date_of_isoweek(2022, 9, '%Y-%m-%d')
end
'2022-02-28'
The process for obtaining the end date in an ISO week is much the same, but instead of appending .monday()
, we append .sunday()
, since all ISO weeks end on a Sunday. We can then run the function to return either a datetime object containing the ISO week end date, or a date string in our chosen format.
def get_end_date_of_isoweek(year, week, date_format='datetime'):
"""
Get the start date of the given ISO week using isocalendar()
Args:
year (int): Year, i.e. 2022
week (int): Week, i.e. 34
date_format (string): Format of the returned date, default is datetime
Returns:
datetime.date: Start date of the given ISO week
"""
if date_format == 'datetime':
return Week(year, week).sunday()
else:
return Week(year, week).sunday().strftime(date_format)
end = get_end_date_of_isoweek(2022, 9)
end
datetime.date(2022, 3, 6)
end = get_end_date_of_isoweek(2022, 9, '%Y-%m-%d')
end
'2022-03-06'
Matt Clarke, Friday, March 18, 2022