abautista
abautista

Reputation: 2780

How to determine all the week numbers in a month with Python?

I have the following problem: Given a year and a month, determine the week numbers that are contained in that particular month, i.e., October 2017 contains week numbers 39,40,41,42,43,44. Caveat: As a rule, week starts in Monday and ends in Sunday. I have a cumbersome code that does the trick but I would like to know if there is a more elegant or Pythonistic way of doing this.

from datetime import datetime
import calendar

def get_week_numbers_in_month(year,month):
    list_of_weeks = []
    initial_day   = 1
    ending_day    = calendar.monthrange(int(year),int(month))[1] #get the last day of month
    initial_week  = int(datetime(year,month,initial_day).isocalendar()[1])
    ending_week   = int(datetime(year,month,ending_day).isocalendar()[1]) 
    counter = initial_week
    while(counter <= ending_week):
        list_of_weeks.append(counter)
        counter += 1
    return list_of_weeks

print("Your month contains the following weeks:\n"+str(get_week_numbers_in_month(2017,10)))
# result: Your month contains the following weeks: 
# [39, 40, 41, 42, 43, 44]

Upvotes: 1

Views: 1596

Answers (3)

Roman Rekrut
Roman Rekrut

Reputation: 53

My approach 😊

from datetime import datetime
import calendar

def get_week_numbers_in_month(year, month) -> list:
    ending_day = calendar.monthrange(year, month)[1]  # get the last day of month
    initial_week = datetime(year, month, 1).isocalendar()[1]
    ending_week = datetime(year, month, ending_day).isocalendar()[1]
    res = list(range(initial_week, ending_week + 1))
    if not res:
        week_num = 52 if initial_week != 53 else 53
        res = list(range(initial_week, week_num + 1)) + list(range(1, ending_week + 1))
    return res

Output

>>> print(get_week_numbers_in_month(2021, 1))
[52, 1, 2, 3, 4]
>>>

Upvotes: 1

Starbuck92
Starbuck92

Reputation: 56

I would have added this as a comment, but do not have enough reputation to do so...

It looks like the approved answer does not actually work for the month of December as it will sometimes spill over into week 1. Also, why is it adding a week to the end when it creates the range?

Accepted answer:

def get_week_numbers_in_month(year,month):
    ending_day    = calendar.monthrange(year, month)[1] #get the last day of month
    initial_week  = datetime(year, month, 1).isocalendar()[1]
    ending_week   = datetime(year, month, ending_day).isocalendar()[1]
    return range(initial_week, ending_week + 1)

print(get_week_numbers_in_month(2019,12))
# range(48, 2)
print(list(get_week_numbers_in_month(2019,12)))
# []

You would actually need to add some additional logic to build the list yourself instead of using a range

def get_week_numbers_in_month(year,month):
    ending_day    = calendar.monthrange(year, month)[1] #get the last day of month
    initial_week  = datetime(year, month, 1).isocalendar()[1]
    ending_week   = datetime(year, month, ending_day).isocalendar()[1]

    # Adding logic to build week list if month is December (12)
    if month = 12:
        week_list = []
        while week != ending_week:
            if week not in week_list:
                week_list.append(week)
            else:
                if week >= 52:
                    week = 1
                else:
                    week += 1
                week_list.append(week)
    else:
        week_list = list(range(initial_week, ending_week))
    return week_list

print(get_week_numbers_in_month(2019,12))
# [48, 49, 50, 51, 52, 1]

Upvotes: 0

Eric Duminil
Eric Duminil

Reputation: 54223

You could simply return a range and avoid the whole initializing process. Also, note that isocalendar returns a 3-tuple of integers:

from datetime import datetime
import calendar

def get_week_numbers_in_month(year,month):
    ending_day    = calendar.monthrange(year, month)[1] #get the last day of month
    initial_week  = datetime(year, month, 1).isocalendar()[1]
    ending_week   = datetime(year, month, ending_day).isocalendar()[1]
    return range(initial_week, ending_week + 1)

print("Your month contains the following weeks:")
print(get_week_numbers_in_month(2017,10))
# range(39, 45)

If you really want to return a list, simply return list(range(...))

Upvotes: 1

Related Questions