Welcome, guest | Sign In | My Account | Store | Cart

13th week of any year is ambiguous without identifying the first week.

This recipe calculates Monday of the first week, not the first Monday, and differs from others by not using flow-control statement (if).

Python, 21 lines
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
#!/usr/bin/env python

from datetime import date, timedelta

def monday_of_week_one(yyyy):
    """ Method to calculate date for Monday of first week of year

    >>> monday_of_week_one(1970)
    datetime.date(1969, 12, 29)
    """

    REF_DAY = date(yyyy, 1, 4)
    DOW = REF_DAY.weekday()
    MONDAY = REF_DAY - timedelta(days = DOW)

    return MONDAY

if __name__ == '__main__':

    import doctest
    doctest.testmod()

Need to know the start date of the 13th week of a year?

To do so, you need to know where to count from.

This reference at wikipedia covers the assumptions made here.

Primarily, it indicates the 1st Thursday of a given year wins the prize, or awards it anyway. It identifies which week is the first week of each [new] year (NY).

The following can be said about the problem:

  • Thursday is 4th day-of-week (DOW-index 3 of 0~6 where Monday = 0)
  • Thursday, January 1st is earliest date in first week of each year
  • Thursday, January 4th is largest date for that DOW
  • First weeks often include dates from prev. year.

These points can be resolved with flow-control:

#!/usr/bin/env python

from datetime import date

NYD = date(1970, 1, 1)
DOW = NYD.weekday()

if DOW > 3:
    week_num = 2
else:
    week_num = 1

Not wrong by any stretch, its readable and easily understood. Exactly why it is a popular solution in other, valid, recipes.

One if-less option uses modulus, spelled out it looks like this:

NYD = date(yr, 1, 1)
DOW = NYD.weekday()
OFFSET = ((3 - DOW) % 7) - 3
MDAY = NYD + timedelta(days = OFFSET)

A cleaner way to do it without an if statement:

REF_DAY = date(1970, 1, 4)
DOW = REF_DAY.weekday()

MONDAY = REF_DAY - timedelta(days = DOW)

The difference is starting, reference-date, as the largest date possible. Then there is no question to flow-control since all else precede this day.

This idea is not limited to this problem, the concept is applicable elsewhere. It always starts by understanding the problem and associated reference points.

Notes:

Other recipes for this remain valid as they continue to solve subsequent problems i.e. date ranges. This calculation is the basis for those additional functions.

I was originally going to title this "I Don't like Mondays", but I feared dating myself. It relates to a bigger problem, sadly not solvable by an integer offset. link

... Edited a couple of times because of stupid formatting issues & typo's, then deciding to make it runnable/testable.

Created by Scott S-Allen on Wed, 31 Oct 2012 (MIT)
Python recipes (4591)
Scott S-Allen's recipes (4)

Required Modules

Other Information and Tasks