How to print a calendar in Python

Learn how to print a calendar in Python. This guide covers various methods, tips, real-world uses, and how to debug common errors.

How to print a calendar in Python
Published on: 
Tue
Apr 21, 2026
Updated on: 
Wed
Apr 22, 2026
The Replit Team

Python's built-in calendar module lets you generate and print calendars with minimal code. This feature is useful for applications that need date displays, schedules, or event management.

In this article, you'll explore different techniques to print calendars. You'll also find practical tips, see real-world applications, and get advice to debug common issues you might face.

Using the calendar module for basic monthly calendar

import calendar
cal = calendar.month(2023, 10)
print(cal)--OUTPUT--October 2023
Mo Tu We Th Fr Sa Su
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 29
30 31

This snippet leverages the calendar module to quickly generate a text-based calendar. The core of this operation is the calendar.month() function, which takes the year and month as integer arguments—in this case, 2023 and 10 for October.

The function doesn't return a data structure like a list; instead, it produces a single, pre-formatted string complete with line breaks and spacing. That's why simply using print(cal) outputs a clean, readable monthly calendar directly to your console without any extra formatting code.

Basic calendar operations

While printing a single month is useful, the calendar module also lets you generate a full year's calendar or even change its fundamental structure.

Using calendar.calendar() to print a full year

import calendar
year_cal = calendar.calendar(2023)
print(year_cal)--OUTPUT--2023

January February March
Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su
1 1 2 3 4 5 1 2 3 4 5
2 3 4 5 6 7 8 6 7 8 9 10 11 12 6 7 8 9 10 11 12
9 10 11 12 13 14 15 13 14 15 16 17 18 19 13 14 15 16 17 18 19
...

Similar to printing a single month, you can generate a full year's calendar using the calendar.calendar() function. It takes the year as its primary argument and returns a pre-formatted string ready for display.

  • The output is automatically arranged in a multi-column format, typically three months across, making it easy to view the entire year at a glance.

Just like with calendar.month(), a simple print() call is all you need to render the complete calendar in your terminal.

Changing the first day of the week with setfirstweekday()

import calendar
calendar.setfirstweekday(6) # 6 = Sunday
print(calendar.month(2023, 10))--OUTPUT--October 2023
Su Mo Tu We Th Fr Sa
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
29 30 31

By default, Python's calendars start on Monday, but you can easily change this with the setfirstweekday() function. This function globally sets the starting day for any calendar you generate afterward.

  • It takes an integer argument where Monday is 0 and Sunday is 6.
  • Calling calendar.setfirstweekday(6) makes Sunday the first column, altering the layout for all subsequent calendar prints.

Working with monthcalendar() to get calendar as a matrix

import calendar
cal_matrix = calendar.monthcalendar(2023, 10)
for week in cal_matrix:
print(" ".join(f"{day:2}" if day != 0 else " " for day in week))--OUTPUT--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 29
30 31

Unlike the previous functions, monthcalendar() gives you raw data to work with. It returns a list of lists, where each inner list represents a week. This structure is essentially a matrix of the month's dates, giving you programmatic control over the calendar's layout and content.

  • Days that fall outside the current month but within the week's structure are represented by a 0.
  • This matrix format is ideal for custom calendar applications, as you can iterate through the weeks and days to add your own logic or formatting.

Advanced calendar techniques

For more granular control than the basic functions offer, you can build custom calendars using the TextCalendar class or even integrate a library like pandas.

Creating a custom formatted calendar

import calendar
from datetime import date

today = date.today()
year, month = today.year, today.month
header = f"{calendar.month_name[month]} {year}"
print(f"{header:^20}")
print("Mo Tu We Th Fr Sa Su")
for week in calendar.monthcalendar(year, month):
print(" ".join(f"{day:2}" if day != 0 else " " for day in week))--OUTPUT--October 2023
Mo Tu We Th Fr Sa Su
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 29
30 31

This approach gives you full control by building the calendar piece by piece. It starts by using the datetime module to fetch the current year and month, making the calendar dynamic. From there, it manually prints a custom header and the days of the week, giving you complete authority over the final look.

  • The core logic loops through the matrix from monthcalendar(), printing each day and using an f-string to format the layout. This method also handles empty day slots, which are represented by 0 in the matrix.

Using TextCalendar class for more formatting options

import calendar
tc = calendar.TextCalendar(firstweekday=0)
formatted_cal = tc.formatmonth(2023, 10, w=3, l=1)
print(formatted_cal)--OUTPUT--October 2023
Mon Tue Wed Thu Fri Sat Sun
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 29
30 31

For more fine-grained control over your calendar's appearance, you can use the TextCalendar class. Unlike the module-level functions, creating a TextCalendar object lets you customize the output with specific formatting arguments.

  • The formatmonth() method accepts a w parameter to set the character width for each day, adjusting horizontal spacing.
  • It also takes an l parameter to define the number of lines per week, which manages vertical spacing.

This gives you a simple way to tweak the layout without manually building the calendar string yourself.

Using pandas for calendar data manipulation

import pandas as pd
import calendar

cal_matrix = calendar.monthcalendar(2023, 10)
df = pd.DataFrame(cal_matrix, columns=["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"])
df = df.replace(0, "")
print(df)--OUTPUT--Mon Tue Wed Thu Fri Sat Sun
0 1
1 2 3 4 5 6 7 8
2 9 10 11 12 13 14 15
3 16 17 18 19 20 21 22
4 23 24 25 26 27 28 29
5 30 31

For more advanced data tasks, you can integrate the pandas library. This approach converts the calendar's matrix structure from monthcalendar() into a DataFrame—a powerful, programmable spreadsheet. It gives you a structured way to handle calendar data for analysis or complex formatting.

  • A DataFrame is created from the matrix, with day names assigned as column headers.
  • The replace(0, "") method then cleans up the output by swapping the placeholder zeros for empty strings, making the final table easier to read.

Move faster with Replit

Replit is an AI-powered development platform that comes with all Python dependencies pre-installed, so you can skip setup and start coding instantly. This lets you move directly from learning techniques, like the ones in this article, to building complete applications.

Instead of piecing together functions like monthcalendar() yourself, you can describe the app you want to build and let Agent 4 take it from idea to working product. For example, you could ask it to build:

  • An event management tool that uses a calendar matrix to highlight important dates and attach notes.
  • A content scheduler that generates a yearly calendar in a pandas DataFrame and exports it to a CSV file.
  • A simple appointment booking utility that displays available time slots on a weekly view.

Simply describe your app, and Replit will write the code, test it, and fix issues automatically, all within your browser.

Common errors and challenges

When working with Python's calendar module, you might run into a few common pitfalls that are easy to avoid with a little foresight.

Fixing incorrect parameter order in calendar.month()

A frequent mistake is mixing up the year and month arguments in the calendar.month() function. It expects the format calendar.month(year, month), but it’s easy to accidentally swap them. This won't always raise an error—if you pass a valid month number (1-12) as the year, you’ll just get a calendar for an ancient year without any warning.

Handling zeros in monthcalendar() output

The monthcalendar() function returns a matrix where days falling outside the current month are represented by a 0. If you forget to handle these placeholders, they will appear in your final output and make the calendar look cluttered. You need to explicitly replace or ignore these 0 values as you iterate through the weeks to generate a clean display.

Correcting global changes with setfirstweekday()

While useful, the setfirstweekday() function applies its change globally. Once you call it, every calendar generated in that script session will start on the new day you've specified. This can cause confusing formatting issues later on if you forget you’ve altered the default setting, so it’s important to be mindful of its persistent effect.

Fixing incorrect parameter order in calendar.month()

The calendar.month() function expects the year first, then the month. Reversing them won't necessarily crash your code, but it will produce the wrong output. Check out the example below, where the arguments are swapped while trying to generate a calendar.

import calendar
# Trying to print January 2023 but parameters are reversed
cal = calendar.month(1, 2023)
print(cal)
# This will display the wrong month (January 1 of some future year)

The function fails because 2023 is passed as the month, which is an invalid value since it must be between 1 and 12. The corrected code below shows how to properly order the arguments to fix this.

import calendar
# Correct parameter order: year, month
cal = calendar.month(2023, 1)
print(cal)
# Now displays January 2023 correctly

The fix is straightforward: always pass the year before the month to the calendar.month() function. An accidental swap, like calendar.month(1, 2023), will fail because the month must be between 1 and 12. By correcting the order to calendar.month(2023, 1), you get the intended calendar. It’s a common slip-up, so it’s a good habit to confirm the argument order when calling functions with multiple numerical inputs.

Handling zeros in monthcalendar() output

The monthcalendar() function returns a matrix where days outside the month appear as 0. These placeholders can easily skew calculations if you don't filter them out. The code below shows how this simple oversight can lead to an incorrect result.

import calendar
cal_matrix = calendar.monthcalendar(2023, 2)
# Trying to count all days in February but includes zeros
total_days = sum(sum(week) for week in cal_matrix)
print(f"February 2023 has {total_days} days")

This code fails because sum() adds the dates themselves (e.g., 1 + 2 + 3) instead of counting the number of non-zero days. This gives you a large, meaningless number. The corrected snippet demonstrates the right way to count.

import calendar
cal_matrix = calendar.monthcalendar(2023, 2)
# Count only non-zero days
total_days = sum(day for week in cal_matrix for day in week if day != 0)
print(f"February 2023 has {total_days} days")

The corrected approach iterates through each week and day in the matrix from monthcalendar(). A simple if day != 0 condition filters out the placeholder zeros, ensuring only actual days are processed.

This is crucial whenever you perform calculations on the matrix. Whether you're counting days or summing values, ignoring the zeros is key to getting accurate results and avoiding skewed data in your application.

Correcting global changes with setfirstweekday()

Because setfirstweekday() applies its change globally, the setting persists even when you generate a new calendar. If you're not careful, a change intended for one calendar will unexpectedly affect another. The following code demonstrates this exact problem.

import calendar
# Set Sunday as first day for one calendar
calendar.setfirstweekday(6) # 6 = Sunday
cal1 = calendar.month(2023, 10)

# Trying to create another calendar with Monday as first day
cal2 = calendar.month(2023, 11) # This will still use Sunday as first day
print(cal1)
print(cal2) # Both use Sunday as first day

The call to setfirstweekday(6) isn't localized. It changes the setting for all subsequent calendars in the script, so cal2 is formatted incorrectly. See how to isolate this change in the corrected snippet that follows.

import calendar
# Create separate calendar instances with different start days
cal1 = calendar.TextCalendar(firstweekday=6) # 6 = Sunday
cal2 = calendar.TextCalendar(firstweekday=0) # 0 = Monday

print(cal1.formatmonth(2023, 10))
print(cal2.formatmonth(2023, 11)) # Each has its own first day setting

To avoid global side effects, use the TextCalendar class instead of the setfirstweekday() function. By creating separate TextCalendar objects, you can pass the starting day as an argument—like TextCalendar(firstweekday=6)—when you create each calendar.

This approach localizes the setting to each specific instance. It ensures that one calendar's formatting doesn't unintentionally alter another, which is crucial when your application requires multiple calendars with different layouts.

Real-world applications

With the common errors out of the way, you can use the calendar module to build practical, real-world applications.

Checking if a date is a weekend using calendar.weekday()

A simple but powerful application is checking whether a specific date is a weekend. The calendar.weekday() function is perfect for this; it takes a year, month, and day, then returns an integer where Monday is 0 and Sunday is 6. Your code can check if the returned value is 5 (Saturday) or 6 (Sunday) to determine if a date falls on a weekend, which is useful for business day calculations or scheduling automated tasks.

Creating a monthly event planner

You can also build a simple event planner by using the matrix returned by monthcalendar() as your foundation. By mapping your events to specific dates in a dictionary, you can loop through the calendar's weeks and days. When a date in the matrix matches a date in your event dictionary, you can display the event details, creating a custom planner without needing a heavy external library.

Checking if a date is a weekend using calendar.weekday()

You can build a simple is_weekend() helper function to check if a delivery is scheduled for a non-business day.

import calendar
from datetime import date

# Function to check if a date is a weekend
def is_weekend(year, month, day):
weekday = calendar.weekday(year, month, day)
return weekday >= 5 # 5 = Saturday, 6 = Sunday

# Check for a delivery date
delivery_date = date(2023, 10, 21) # A Saturday
if is_weekend(delivery_date.year, delivery_date.month, delivery_date.day):
print(f"{delivery_date} is a weekend - no deliveries available")
else:
print(f"{delivery_date} is a weekday - delivery available")

This code creates a reusable function, is_weekend, that checks if a date is a Saturday or Sunday. It uses the datetime module to create a specific date object for testing.

  • The function calls calendar.weekday(), which returns a number representing the day of the week.
  • Its logic hinges on the simple check weekday >= 5, which returns True if the day is either Saturday (5) or Sunday (6).

Finally, it passes a sample delivery_date to the function to demonstrate a practical use case for scheduling.

Creating a monthly event planner

You can combine the monthcalendar() matrix with a dictionary to build a simple but effective event planner.

This approach starts by defining an events dictionary, where each key is a day of the month and its value is the event's description. This dictionary acts as a simple database for all your important dates.

  • The code then generates a calendar grid and iterates through it, checking if each day is a key in the events dictionary.
  • If a day matches an event, it’s marked with an asterisk, giving you a quick visual cue for busy days.

To supplement the grid, the code also prints a formatted list of events below. It loops through the sorted events dictionary and uses helpers like calendar.day_name to create a clear, readable schedule that details each appointment.

import calendar

# Create a monthly event planner with important dates
year, month = 2023, 11 # November 2023
events = {15: "Team Meeting", 24: "Project Deadline"}

# Print the calendar with events marked
cal = calendar.monthcalendar(year, month)
print(f"{calendar.month_name[month]} {year} Events")
print("Mo Tu We Th Fr Sa Su")

for week in cal:
week_str = ""
for day in week:
if day == 0:
week_str += " "
elif day in events:
week_str += f"{day:2}*" # Mark days with events
else:
week_str += f"{day:2} "
print(week_str)

print("\nEvent Schedule:")
for day, event in sorted(events.items()):
weekday = calendar.weekday(year, month, day)
print(f"{day} {calendar.month_abbr[month]} ({calendar.day_name[weekday]}): {event}")

This code demonstrates how to use a dictionary as a single source of truth for event data. The events dictionary holds all appointments, which are then used to generate two different views of the schedule.

  • The first part creates a visual calendar grid. It uses the in operator to quickly check if a day from the monthcalendar() matrix exists as a key in the events dictionary, marking it if so.
  • The second part generates a clean, text-based agenda by iterating directly over the events dictionary itself.

Get started with Replit

Now, turn these concepts into a real tool. Describe what you want to build to Replit Agent, like “a business day calculator that skips weekends” or “a CLI tool that generates a yearly event calendar.”

Replit Agent will write the code, test for errors, and deploy your application for you. Start building with Replit and create your first project in seconds.

Get started free

Create and deploy websites, automations, internal tools, data pipelines and more in any programming language without setup, downloads or extra tools. All in a single cloud workspace with AI built in.

Get started free

Create and deploy websites, automations, internal tools, data pipelines and more in any programming language without setup, downloads or extra tools. All in a single cloud workspace with AI built in.