Conversion from calendar week to date

Sometimes one has to convert a date written as year, calendar week (CW), and day of week to an actual date with month and date. The behaviour in the begin/end of a year may be not straightforward. For example according to ISO 8601 monday date of the CW 1 year 2019 is 31 January 2018. As far as I can see there is no standard function for conversion in python.

I use the following hacky code:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
def year_cw_day_to_date(year: int, calendar_week: int, day_of_week: int):
    """
    year: integer number, e.g. 1986
    calendar_week: integer number, from 1 to 53
    day_of_week: integer starting from 1, so that 1 is Monday, 2 is Tuesday, ...,  7 is Sunday

    >>> year_cw_day_to_date(2019, 1, 1)
    datetime.date(2018, 12, 31)

    >>> year_cw_day_to_date(2019, 1, 7)
    datetime.date(2019, 1, 6)

    >>> year_cw_day_to_date(2018, 52, 7)
    datetime.date(2018, 12, 30)

    >>> year_cw_day_to_date(2018, 53, 2)
    datetime.date(2019, 1, 1)

    >>> year_cw_day_to_date(2018, 53, 0)
    Traceback (most recent call last):
    ...
    ValueError: day_of_week must be in range from 1 to 7
    """

    if day_of_week not in range(1, 8):
        raise ValueError("day_of_week must be in range from 1 to 7")
    string_representation = f"{year}-{calendar_week}-{day_of_week}"
    return datetime.datetime.strptime(string_representation, "%G-%V-%u").date()

It prints the week-based date to a string and then parses it using %V and %u format from python 3 (docs) Therefore you don’t need to implement ISO logic of dates calculation. Hopefully such a funciton apppear in standard library.

Python 2 doesn’t have these %V and %u implemented. :(

Measuring elapsed time

Python standard library has a set of functions to measure elapsed time.

One can get information about each function using time.get_clock_info(name)

ClockAdjustableMonotonicResolutionTick Rate
process_timeFalseTrue1e-0710,000,000
clockFalseTrue4.665306263360271e-072,143,482
perf_counterFalseTrue4.665306263360271e-072,143,482
monotonicFalseTrue0.01562564
timeTrueFalse0.01562564

source of measurements: Python Clocks Explained, 2015.

time.perf_counter() gives the most accurate results when testing the difference between two times and pretty fast. timeit uses time.perf_counter() by default.

time.process_time() can be helpful to understand how long different parts of a program took to run.

according to the PEP 0418, several modules use (or could use) time.monotonic(), including concurrent.futures, multiprocessing, queue, subprocess, telnet and threading modules to implement timeout.

See also