Skip to Content
Course content

221: The calendar Module

Click on the "Edit" button in the top corner of the screen to edit your slide content.

I see this all the time: students assume the calendar module is just a fancy way to print a grid of numbers to the terminal. They'll try it once with calendar.month(2023, 10), see a pretty text calendar, and then move right back to the datetime module for everything else, thinking calendar has no "real" programmatic utility.

Here is why that's a mistake. If you rely solely on datetime to figure out, say, how many days are in February of a leap year, you end up writing clunky logic or catching ValueError exceptions just to probe the boundaries of a month. That's a waste of your time and makes your code harder to read.

Thinking it's just a formatting tool for the console

import calendar

# The "toy" use case most people stop at
print(calendar.month(2024, 2))

If you think the above is the only value of the module, you're missing the engine under the hood. The calendar module isn't about displaying dates; it's about the structure of the Gregorian calendar. While datetime tells you "What time is it right now?", calendar tells you "How does the month of March behave in a leap year?"

Using calendar for structural date logic

One of the most useful functions you'll actually use in production is monthrange(). It returns a tuple containing the day of the week of the first day of the month and the number of days in the month. No more guessing if it's 28, 30, or 31 days.

import calendar

# Let's find out how many days are in February 2024 (a leap year)
first_weekday, num_days = calendar.monthrange(2024, 2)

print(f"February 2024 has {num_days} days.") 
# Output: February 2024 has 29 days.

I've spent hours in the past manually calculating leap years with if year % 4 == 0... logic. Please, don't do that. Just use calendar.isleap(year). It's cleaner, it's tested, and it handles the weird century rules (like 1900 not being a leap year, but 2000 being one) that you'll probably forget to code.

Iterating over dates with the Calendar class

If you need to generate a list of all dates in a month for a scheduling app, don't just loop from 1 to 31 and hope for the best. The Calendar class provides a more professional way to handle this. By creating an instance of calendar.Calendar(), you can use itermonthdays2(), which yields tuples of (day of month, day of week).

import calendar

cal = calendar.Calendar()

# itermonthdays2 gives us (day, weekday)
# Day 0 represents days that belong to the previous or next month 
# to fill out the week grid.
for day, weekday in cal.itermonthdays2(2023, 10):
    if day != 0:
        print(f"Day {day} is weekday {weekday}")

I prefer this approach because it keeps the date logic separated from the display logic. You get a clean stream of data that you can filter or transform before you ever decide how to show it to the user.




📋 Practical Task

The Business Month-End Date Finder

In many financial applications, you need to find the "last business day" of a month (Monday through Friday). If the last day of the month falls on a Saturday, the last business day is Friday. If it falls on a Sunday, it's also Friday.

Your Task: Write a function called get_last_business_day(year, month) that uses the calendar module to return the date of the last weekday of the given month.

  • Use calendar.monthrange() to find the total number of days in the month.
  • Use the weekday() method from the datetime.date class (or calendar.weekday()) to determine what day of the week that last day is.
  • If the last day is Saturday (5), subtract 1 day.
  • If the last day is Sunday (6), subtract 2 days.
  • Return a datetime.date object representing that final business day.

Example Test: For October 2023, the 31st was a Tuesday, so it should return 2023-10-31. For June 2024, the 30th is a Sunday, so it should return 2024-06-28.

Rating
0 0

There are no comments for now.

to be the first to leave a comment.