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
!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
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()
week = get_iso_week_from_date('2022-02-28') week
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
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
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
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
Matt Clarke, Friday, March 18, 2022