import calendar
from pathlib import Path
import matplotlib.pyplot as plt
import matplotlib
from matplotlib.patches import Rectangle
matplotlib.use("Agg")
def draw_pretty_calendar_grid(
year,
month,
week_start="mon",
title=None,
landscape=True,
dpi=300,
outdir=Path("."),
fmts=["pdf", "png"],
style="classic",
draw_grid=True,
):
a4_w, a4_h = 8.27, 11.69
if landscape:
a4_w, a4_h = a4_h, a4_w
fig, ax = plt.subplots(figsize=(a4_w, a4_h), dpi=dpi)
ax.set_axis_off()
margin = 0.05
fig.subplots_adjust(left=margin, right=1-margin, top=1-margin, bottom=margin)
_title = title or f"{calendar.month_name[month]} {year}"
title_color = "#2E8B57"
title_fontsize = 36
title_rel_height = title_fontsize / (dpi * a4_h)
ax.text(
0.5,
1.0,
_title,
ha="center",
va="top",
fontsize=title_fontsize,
fontweight="bold",
color=title_color,
transform=ax.transAxes,
)
blank_height = 0.04
weekday_height = 0.06
n_cols = 7
labels = list(calendar.day_abbr)
firstweekday = 0 if week_start == "mon" else 6
calendar.setfirstweekday(firstweekday)
if week_start != "mon":
labels = labels[-1:] + labels[:-1]
y_weekday_bottom = 1.0 - margin - title_rel_height - weekday_height + 0.02 * weekday_height
for c, day in enumerate(labels):
x_pos = c / n_cols + 0.02 / n_cols
ax.text(
x_pos,
y_weekday_bottom,
day,
ha="left",
va="bottom",
fontsize=20,
fontweight="bold",
transform=ax.transAxes,
)
month_matrix = calendar.monthcalendar(year, month)
n_rows = len(month_matrix)
calendar_space = 1.0 - margin - title_rel_height - weekday_height - blank_height
cell_h = calendar_space / n_rows
cell_w = 1.0 / n_cols
x0, y0 = 0, 0
for r, week in enumerate(month_matrix):
for c, day in enumerate(week):
if day != 0:
x_left = x0 + c * cell_w
y_bottom = y0 + (n_rows - r - 1) * cell_h
weekend_color = "#D3D3D3"
weekend_cols = [5, 6] if week_start == "mon" else [6, 0]
if c in weekend_cols:
rect = Rectangle(
(x_left, y_bottom),
cell_w,
cell_h,
facecolor=weekend_color,
edgecolor=None,
transform=ax.transAxes,
zorder=0,
)
ax.add_patch(rect)
padding_x = 0.05 * cell_w
padding_y = 0.05 * cell_h
x_pos = x0 + c * cell_w + padding_x
y_pos = y0 + (n_rows - r - 1) * cell_h + cell_h - padding_y
ax.text(
x_pos,
y_pos,
str(day),
ha="left",
va="top",
fontsize=20,
transform=ax.transAxes,
)
if draw_grid:
for r, week in enumerate(month_matrix):
for c, day in enumerate(week):
x_left = x0 + c * cell_w
y_bottom = y0 + (n_rows - r - 1) * cell_h
rect = Rectangle(
(x_left, y_bottom),
cell_w,
cell_h,
fill=False,
edgecolor="black",
lw=0.8,
transform=ax.transAxes
)
ax.add_patch(rect)
outdir.mkdir(parents=True, exist_ok=True)
grid_tag = "grid" if draw_grid else "line"
stem = f"calendar_{year}_{month:02d}_{style}{'_landscape' if landscape else ''}_{grid_tag}"
for f in fmts:
path = outdir / f"{stem}.{f}"
fig.savefig(path, dpi=dpi)
print(f"Saved -> {path.resolve()}")
plt.close(fig)
draw_pretty_calendar_grid(2025, 8, style="colorful", fmts=["png"], draw_grid=False)
draw_pretty_calendar_grid(2025, 8, style="colorful", fmts=["png"], draw_grid=True)
For further actions, you may consider blocking this person and/or reporting abuse
Top comments (1)
Your script already creates a visual monthly calendar using Python. It uses the
calendar
module to get the month layout andmatplotlib
to draw each day as a rectangle, with weekends optionally highlighted. You can customize the start of the week, orientation (landscape/portrait), grid lines, and output format (png
,pdf
). Simply calldraw_pretty_calendar_grid(year, month, fmts=["png"], draw_grid=True)
to generate a calendar image, and loop through months to create a full-year calendar. You can also extend it to show events by adding text or colored highlights on specific days.