← 返回Python标准库精讲目录
← 返回学习笔记首页
专题: Python标准库精讲系统学习
关键词: Python, 标准库, calendar, 日历, 月历, 年历, Calendar, TextCalendar, HTMLCalendar, isleap, weekday
一、calendar模块概述
Python的calendar模块是标准库中专门用于处理日历相关操作的工具模块。它提供了一系列函数和类,支持生成文本格式和HTML格式的日历、处理星期和月份信息、判断闰年、计算日期对应的星期等常见需求。calendar模块与datetime模块相辅相成:datetime专注于单个日期时间的精确计算和操作,而calendar则擅长宏观的日历展示和周期性日期计算。
calendar模块的核心设计围绕"日历"这一抽象概念展开,提供了一个基类Calendar和多个子类(TextCalendar、HTMLCalendar、LocalTextCalendar、LocaleHTMLCalendar),形成了清晰的类继承体系。开发者可以根据输出格式需求选择合适的子类,也可以继承Calendar类扩展自定义日历行为。
模块内置了两组重要常量:星期的英文名称列表(MONDAY到SUNDAY)和月份的英文名称列表(JANUARY到DECEMBER),便于国际化展示和日期计算中的引用。此外,calendar模块还提供了若干便捷的基础函数,无需实例化类即可直接调用,适合快速完成简单的日历操作。
import calendar
# 查看日历模块的所有可用成员
print(dir(calendar))
# 输出中包含:Calendar, TextCalendar, HTMLCalendar,
# isleap, leapdays, weekday, monthrange,
# month_name, day_name, prcal, prmonth 等
二、基础函数 — 快速日历操作
calendar模块提供了多个可直接调用的基础函数,覆盖了日历生成、闰年判断、星期计算等常见场景。这些函数不需要创建任何对象即可使用,适合简单的脚本任务或快速原型开发。
2.1 文本月历与年历生成
month( year, month, w=2, l=1 )函数返回指定年月的文本月历字符串。参数w表示日期之间间隔的字符宽度,l表示每周之间间隔的行数。prmonth( year, month, w=2, l=1 )则直接打印结果,不返回字符串。
import calendar
# 生成2026年5月的月历字符串
may_cal = calendar.month(2026, 5)
print(may_cal)
# 直接打印月历
calendar.prmonth(2026, 5)
# 输出:
# May 2026
# 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
calendar( year, w=2, l=1, c=6, m=3 )函数返回整年的年历字符串,参数c表示月份之间的水平间隔宽度,m表示每行显示的月份数。prcal( year, w=2, l=1, c=6, m=3 )则直接打印。
import calendar
# 生成2026年的年历(每行3个月)
year_cal = calendar.calendar(2026, c=3, m=3)
print(year_cal)
# 直接打印
calendar.prcal(2026)
2.2 闰年判断与相关计算
isleap( year )判断指定年份是否为闰年,返回布尔值。闰年的判断规则为:能被4整除但不能被100整除的年份,或者能被400整除的年份。leapdays( y1, y2 )返回y1年到y2年之间(包含y1,不包含y2)的闰年总数。
import calendar
# 判断闰年
print(calendar.isleap(2024)) # True
print(calendar.isleap(2025)) # False
print(calendar.isleap(2026)) # False
print(calendar.isleap(2000)) # True (能被400整除)
print(calendar.isleap(1900)) # False (能被100整除但不能被400整除)
# 计算闰年数量
print(calendar.leapdays(2000, 2026)) # 7个闰年
2.3 星期与月份信息计算
weekday( year, month, day )返回指定日期对应的星期索引,0表示星期一,6表示星期日。monthrange( year, month )返回一个元组 ( weekday_of_first_day, number_of_days_in_month ),即该月第一天的星期索引和该月的总天数。这两个函数是日常开发中最高频使用的基础工具。
import calendar
# 计算某天是星期几 (0=星期一, 6=星期日)
w = calendar.weekday(2026, 5, 5)
print(w) # 1 — 星期二
print(calendar.day_name[w]) # Tuesday
# 获取某月第一天是星期几和该月天数
first_weekday, days_in_month = calendar.monthrange(2026, 5)
print(first_weekday) # 3 — 5月1日是星期四
print(days_in_month) # 31 — 5月有31天
# 简化:判断某日是否为周末
def is_weekend(y, m, d):
w = calendar.weekday(y, m, d)
return w >= 5 # 星期六=5, 星期日=6
print(is_weekend(2026, 5, 5)) # False (星期二)
print(is_weekend(2026, 5, 9)) # True (星期六)
2.4 星期与月份名称常量
calendar模块提供了两组非常有用的常量列表。day_name和day_abbr分别存储星期全称和缩写(英文)。month_name和month_abbr分别存储月份全称和缩写(英文)。常量索引从0开始,其中month_name[0]和day_abbr[0]为空字符串,实际内容从索引1开始。
import calendar
# 星期名称
print(list(calendar.day_name))
# ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday']
print(list(calendar.day_abbr))
# ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
# 月份名称
print(list(calendar.month_name))
# ['', 'January', 'February', 'March', 'April', 'May', 'June',
# 'July', 'August', 'September', 'October', 'November', 'December']
print(list(calendar.month_abbr))
# ['', 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
# 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
# 实际应用:将数字月份转为中文名称
month_num = 5
en_name = calendar.month_name[month_num] # 'May'
print(f"{month_num}月对应的英文名称为:{en_name}")
2.5 其他实用函数
setfirstweekday( weekday )设置每周的第一天(默认是星期一)。firstweekday()返回当前设置的每周第一天。timegm( tuple )将struct_time元组转换为时间戳(秒数),与time.gmtime()功能互逆。
import calendar
import time
# 设置每周第一天为星期日
calendar.setfirstweekday(calendar.SUNDAY)
print(calendar.firstweekday()) # 6
calendar.prmonth(2026, 5) # 星期日排在第一列
# 恢复为星期一
calendar.setfirstweekday(calendar.MONDAY)
# timegm: 将时间元组转为时间戳
t = (2026, 5, 5, 12, 0, 0, 0, 0, 0)
timestamp = calendar.timegm(t)
print(timestamp) # 对应的UTC时间戳
print(time.gmtime(timestamp)) # 还原回struct_time
三、Calendar基类 — 日期迭代器
Calendar类是calendar模块的核心基类,它封装了日历数据生成的通用逻辑。Calendar类的构造函数接受可选参数firstweekday(整数0-6,默认0表示星期一),用于指定每周的第一天。Calendar本身不直接生成可视化的日历输出,而是作为数据迭代器提供各种日期集合,供其子类(TextCalendar、HTMLCalendar)渲染使用。
3.1 星期的迭代
iterweekdays()返回一个迭代器,按当前设置的每周第一天顺序迭代星期的索引值(0-6)。这个方法常用于生成日历表头。
import calendar
cal = calendar.Calendar()
# 默认星期一为每周第一天
for wd in cal.iterweekdays():
print(wd, calendar.day_name[wd])
# 输出:
# 0 Monday
# 1 Tuesday
# 2 Wednesday
# 3 Thursday
# 4 Friday
# 5 Saturday
# 6 Sunday
# 若设置星期日为每周第一天
cal_sun = calendar.Calendar(firstweekday=6)
for wd in cal_sun.iterweekdays():
print(wd, calendar.day_name[wd])
# 输出:
# 6 Sunday
# 0 Monday
# 1 Tuesday
# 2 Wednesday
# 3 Thursday
# 4 Friday
# 5 Saturday
3.2 日期的迭代方法
Calendar类提供了多种日期迭代方法,以不同的粒度遍历指定月份或年份的日期数据。
itermonthdates( year, month ) :返回一个迭代器,遍历指定月份的所有日期,会向前后填充必要的前月/后月日期以补满整周(从周日或周一开始取决于设置),每个元素是一个datetime.date对象。
import calendar
cal = calendar.Calendar()
for d in cal.itermonthdates(2026, 5):
print(d, end=' ')
# 输出包含4月27日到5月31日的完整周期
# 因为5月1日是星期四,前4天(4月27-30日)会被包含进来
itermonthdays( year, month ) :与itermonthdates类似,但返回的整数是月份中的日期号(1-31)。不在本月的日期用0表示。这种方法更适合纯数值计算。
import calendar
cal = calendar.Calendar()
for d in cal.itermonthdays(2026, 5):
print(f'{d:2d}', end=' ')
# 输出: 0 0 0 0 1 2 3 ...
# 前4个0代表4月最后4天不在5月
itermonthdays2( year, month ) :返回 ( 日期号, 星期索引 ) 元组的迭代器。不在本月的日期号为0。
import calendar
cal = calendar.Calendar()
for day_num, wd in cal.itermonthdays2(2026, 5):
if day_num != 0:
print(f'{day_num}日 = {calendar.day_name[wd]}')
# 输出过滤掉不在5月份的所有日期
itermonthdays3( year, month ) :返回 ( 年份, 月份, 日期号 ) 元组的迭代器。与itermonthdays2相比,多包含了年份和月份信息,便于处理跨月边缘的日期。
import calendar
cal = calendar.Calendar()
for y, m, d in cal.itermonthdays3(2026, 5):
if d == 1:
print(f'本月1日对应: {y}-{m}-{d}')
break
print(f'跨月日期: {y}-{m}-{d}')
# 跨越到5月的日期会显示为 (2026, 5, 1)
# 从4月跨越来的日期会显示为 (2026, 4, 27) 等
3.3 周列表与月列表方法
除了迭代器方法,Calendar还提供了返回列表的方法,将日期按周分组,结构更清晰。
monthdatescalendar( year, month ) :返回一个列表,每个元素是一周的日期列表(datetime.date),不足整月的两侧用前后月日期补全。
import calendar
cal = calendar.Calendar()
weeks = cal.monthdatescalendar(2026, 5)
for i, week in enumerate(weeks, 1):
print(f'第{i}周:', week)
# 输出5月的每一周,共6周
monthdayscalendar( year, month ) :同上,但每个元素是日期号,非本月日期用0表示。
monthdays2calendar( year, month ) :同上,但每个元素是 ( 日期号, 星期索引 ) 元组。
import calendar
cal = calendar.Calendar()
# monthdayscalendar
for week in cal.monthdayscalendar(2026, 5):
print(week)
# monthdays2calendar
for week in cal.monthdays2calendar(2026, 5):
print(week)
# 输出:
# [(0, 0), (0, 0), (0, 0), (0, 0), (1, 3), (2, 4), (3, 5)]
# [(4, 6), (5, 0), (6, 1), (7, 2), (8, 3), (9, 4), (10, 5)]
# ...
3.4 年列表方法
Calendar类还提供了按年组织数据的列表方法,适合生成全年日历数据。
yeardatescalendar( year, width=3 ) :返回年历数据列表。width参数控制每行显示几个月。返回的三级嵌套列表结构为:[ 行列表 ],每行包含width个月,每月包含若干周,每周包含若干datetime.date对象。
yeardays2calendar( year, width=3 ) :返回每月的 ( 日期号, 星期索引 ) 结构,日期号为0表示不属于本月。
import calendar
cal = calendar.Calendar()
# 每行显示3个月的全年日期数据
year_data = cal.yeardatescalendar(2026, width=3)
# year_data[row_index][month_index][week_index][day_index]
# 遍历第1行第1个月(1月)的所有周
for week in year_data[0][0]:
for day in week:
print(day, end=' ')
print()
# 输出1月份按周排列的日历数据
四、子类详解 — 多样化的日历输出
Calendar类提供了原始的日期数据迭代器,但实际生成可视化日历的任务由它的子类完成。TextCalendar生成格式化的文本日历,HTMLCalendar生成可用于网页的HTML日历代码。LocalTextCalendar和LocaleHTMLCalendar则支持本地化处理。
4.1 TextCalendar — 文本日历
TextCalendar继承自Calendar,覆写了formatmonth、formatyear等方法,生成对齐良好的纯文本日历字符串。它复用了父类的日期迭代逻辑,在此基础上添加了格式化和对齐代码。
import calendar
# 创建文本日历对象
tc = calendar.TextCalendar()
# 生成文本月历
month_str = tc.formatmonth(2026, 5)
print(month_str)
# May 2026
# 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
# 生成文本年历
year_str = tc.formatyear(2026, c=3, m=3)
print(year_str)
# 直接打印
tc.prmonth(2026, 5)
tc.pryear(2026)
formatmonth方法返回的是字符串,prmonth直接打印;formatyear和pryear同理。TextCalendar的formatmonth实际上调用了父类的monthdatescalendar等技术方法来获取数据,然后渲染成文本格式。
4.2 HTMLCalendar — 网页日历
HTMLCalendar继承自Calendar,生成的是HTML表格格式的日历代码,可以直接嵌入网页中使用。它提供了formatmonth和formatyear等方法,返回包含table、tr、td等HTML标签的字符串。
import calendar
hc = calendar.HTMLCalendar()
# 生成HTML月历
html_month = hc.formatmonth(2026, 5)
print(html_month)
# 输出:
#
# May 2026
# Mon Tue ...
# ...
# 1 ...
#
# 保存为HTML文件
with open('calendar_2026_05.html', 'w', encoding='utf-8') as f:
f.write(f'{html_month}')
formatyear( year, width=3 )生成整年的HTML日历,每行显示width个月。
import calendar
hc = calendar.HTMLCalendar()
# 生成全年HTML日历
html_year = hc.formatyear(2026, width=3)
# 自定义CSS类名
# HTMLCalendar生成的表格默认使用cssclasses类名
# 可以通过cssclasses属性自定义
hc.cssclasses = ['mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun']
# 默认的cssclasses为:
# ['mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun']
# 传入自定义CSS
# 还可以设置cssclasses_month_head和cssclasses_year_head
# 来控制月份标题的样式
CSS类名定制是HTMLCalendar的一个重要特性。默认的cssclasses为['mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun'],开发者可以替换为自己的类名,配合CSS实现个性化的日历样式。例如周末用不同颜色标记、当天高亮等效果。
4.3 本地化子类
LocalTextCalendar和LocaleHTMLCalendar是支持本地化的子类,它们继承自TextCalendar和HTMLCalendar,构造函数接受locale参数,用于指定区域代码,从而输出本地化语言的星期和月份名称。
import calendar
import locale
# 查看系统支持的locale
# locale -a 在命令行查看所有可用locale
# 创建中文本地化日历对象
try:
# 尝试设置中文locale
locale.setlocale(locale.LC_ALL, 'zh_CN.UTF-8')
ltc = calendar.LocalTextCalendar(locale='zh_CN.UTF-8')
ltc.prmonth(2026, 5)
# 月份和星期名称将显示为中文
except locale.Error:
print('当前系统不支持zh_CN.UTF-8 locale')
# 创建其他语言本地化日历
# ltc_fr = calendar.LocalTextCalendar(locale='fr_FR.UTF-8')
# ltc_de = calendar.LocalTextCalendar(locale='de_DE.UTF-8')
# 使用本地化的HTMLCalendar
try:
lhc = calendar.LocaleHTMLCalendar(locale='zh_CN.UTF-8')
html_month_cn = lhc.formatmonth(2026, 5)
print(html_month_cn)
except locale.Error:
print('本地化HTMLCalendar创建失败')
# 注:Windows系统上locale名称可能不同,如 'Chinese_China.936'
需要注意的是,本地化子类的有效性依赖于操作系统对指定locale的支持。在Windows和Linux系统上,locale名称格式可能不同。Windows通常使用类似'Chinese_China.936'的格式,而Linux使用'zh_CN.UTF-8'。
五、实战应用 — 日历模块的场景化实践
calendar模块在实际开发中有广泛的应用场景,从简单的日期计算到复杂的周期性事件管理。以下介绍几个典型的实战案例,展示如何将calendar模块的各种功能组合起来解决实际问题。
5.1 工作日计算器
使用calendar模块可以轻松实现指定月份的工作日计算功能。通过遍历月份的所有日期,排除周末(星期六和星期日),即可得到工作日列表。如果需要排除法定节假日,可以在基础逻辑上进一步过滤。
import calendar
from datetime import date, timedelta
def get_workdays(year, month, holidays=None):
"""获取指定月份的所有工作日(排除周末和可选节假日)"""
holidays = holidays or []
cal = calendar.Calendar()
workdays = []
for day_num, wd in cal.itermonthdays2(year, month):
if day_num == 0:
continue # 跳过不在本月的日期
if wd >= 5:
continue # 跳过周末
d = date(year, month, day_num)
if d in holidays:
continue # 跳过节假日
workdays.append(d)
return workdays
# 示例:2026年5月的工作日
holidays_2026_05 = [
date(2026, 5, 1), # 劳动节
]
workdays = get_workdays(2026, 5, holidays_2026_05)
print(f'2026年5月工作日共计:{len(workdays)}天')
for d in workdays:
print(d, calendar.day_name[d.weekday()])
# 计算工作日比例
total_days = calendar.monthrange(2026, 5)[1]
print(f'工作日占比:{len(workdays)}/{total_days} = {len(workdays)/total_days*100:.1f}%')
5.2 会议日期生成器
在实际办公场景中,经常需要生成周期性会议的日期安排,比如"每月第二个星期二"开会。利用calendar模块的日期迭代功能,可以精准定位这类相对日期。
import calendar
from datetime import date
def nth_weekday(year, month, weekday, nth):
"""计算某月第n个指定星期几的日期
参数:
weekday: 0=星期一 ... 6=星期日
nth: 1=第一个, 2=第二个, ... -1=最后一个
返回:date对象或None
"""
cal = calendar.Calendar()
# 收集该月所有指定星期几的日期
matches = []
for day_num, wd in cal.itermonthdays2(year, month):
if day_num != 0 and wd == weekday:
matches.append(day_num)
if not matches:
return None
if nth > 0 and nth <= len(matches):
return date(year, month, matches[nth - 1])
elif nth == -1:
return date(year, month, matches[-1])
return None
# 示例:2026年5月第二个星期二
meeting_day = nth_weekday(2026, 5, 1, 2) # 1=Tuesday
print(f'本月第二次周二例会日期:{meeting_day}')
# 输出:2026-05-12
# 示例:每月最后一个星期五
last_friday = nth_weekday(2026, 5, 4, -1) # 4=Friday
print(f'本月最后一个周五:{last_friday}')
# 输出:2026-05-29
# 生成全年所有第二个星期三的会议日程
def generate_meeting_schedule(year, weekday, nth):
meetings = []
for month in range(1, 13):
d = nth_weekday(year, month, weekday, nth)
if d:
meetings.append(d)
return meetings
schedule = generate_meeting_schedule(2026, 2, 2) # 每月第二个周三
print('2026年所有第二个周三的会议日期:')
for d in schedule:
print(f' {d} — {calendar.day_name[d.weekday()]}')
5.3 日历Web组件
利用HTMLCalendar的定制能力,可以构建功能完整的Web日历组件。通过自定义CSS类名和添加额外处理逻辑,实现交互式日历。
import calendar
from datetime import date
class StyledHTMLCalendar(calendar.HTMLCalendar):
"""扩展HTMLCalendar,添加自定义样式处理"""
def __init__(self, firstweekday=0):
super().__init__(firstweekday)
self.cssclasses = [
'cal-mon', 'cal-tue', 'cal-wed', 'cal-thu',
'cal-fri', 'cal-sat', 'cal-sun'
]
self.cssclasses_weekday_head = [
'cal-head-mon', 'cal-head-tue', 'cal-head-wed',
'cal-head-thu', 'cal-head-fri', 'cal-head-sat',
'cal-head-sun'
]
def formatday(self, day, weekday):
"""覆写单日格式化方法,支持高亮今天"""
if day == 0:
return '
'
today = date.today()
css_class = self.cssclasses[weekday]
# 高亮今天
if (self.year == today.year and
self.month == today.month and
day == today.day):
css_class += ' today'
# 周末特殊样式
if weekday >= 5:
css_class += ' weekend'
return f'{day} '
def formatmonth(self, year, month):
"""覆写,保存年月信息供formatday使用"""
self.year = year
self.month = month
return super().formatmonth(year, month)
# 使用自定义日历
cal = StyledHTMLCalendar()
html_output = cal.formatmonth(2026, 5)
print(html_output)
# 配套CSS示例(配合上述HTML使用):
css_example = '''
.month { border-collapse: collapse; width: 100%; }
.month th { background: #2c3e50; color: #fff; padding: 8px; }
.cal-mon, .cal-tue, .cal-wed, .cal-thu, .cal-fri { padding: 8px; text-align: center; }
.cal-sat, .cal-sun { padding: 8px; text-align: center; color: #e74c3c; }
.today { background: #3498db; color: #fff; font-weight: bold; border-radius: 50%; }
.weekend { background: #fdf0f0; }
.noday { border: none; }
'''
5.4 日期范围实用工具
结合calendar和datetime模块,可以构建实用的日期范围计算工具。
import calendar
from datetime import date, timedelta
def month_boundaries(year, month):
"""获取指定月份的第一天和最后一天"""
first_day = date(year, month, 1)
_, days_in_month = calendar.monthrange(year, month)
last_day = date(year, month, days_in_month)
return first_day, last_day
def week_boundaries(year, month, day):
"""获取指定日期所在周的周一和周日"""
wd = calendar.weekday(year, month, day)
d = date(year, month, day)
monday = d - timedelta(days=wd)
sunday = monday + timedelta(days=6)
return monday, sunday
def quarter_months(year, quarter):
"""获取指定季度的3个月份"""
months = [(quarter - 1) * 3 + i + 1 for i in range(3)]
result = []
for m in months:
first, last = month_boundaries(year, m)
result.append((m, first, last))
return result
# 示例
first, last = month_boundaries(2026, 5)
print(f'2026年5月范围:{first} ~ {last}')
mon, sun = week_boundaries(2026, 5, 15)
print(f'2026年5月15日所在周:{mon} ~ {sun}')
q2 = quarter_months(2026, 2)
print('2026年第二季度:')
for m, f, l in q2:
print(f' {calendar.month_name[m]}: {f} ~ {l}')
5.5 年龄与生日计算
日历模块还常用于涉及月份的计算,如精确年龄计算。结合datetime可以获得比单纯日期加减更准确的结果。
import calendar
from datetime import date
def calculate_age(birth_date, target_date=None):
"""计算到目标日期的精确年龄(周岁)"""
if target_date is None:
target_date = date.today()
age = target_date.year - birth_date.year
# 检查是否已过生日
if (target_date.month, target_date.day) < (birth_date.month, birth_date.day):
age -= 1
# 返回年龄和剩余天数
next_birthday_year = target_date.year + (1 if age == 0 else 0)
# 考虑闰年2月29日情况
if birth_date.month == 2 and birth_date.day == 29:
if not calendar.isleap(next_birthday_year):
next_birthday = date(next_birthday_year, 3, 1)
else:
next_birthday = date(next_birthday_year, 2, 29)
else:
next_birthday = date(next_birthday_year, birth_date.month, birth_date.day)
days_until_birthday = (next_birthday - target_date).days
return age, days_until_birthday
# 示例
birth = date(1990, 7, 15)
today = date(2026, 5, 5)
age, days_left = calculate_age(birth, today)
print(f'出生日期:{birth}')
print(f'当前年龄:{age}周岁')
print(f'距离下次生日还有:{days_left}天')
六、核心总结
calendar模块是Python标准库中日历操作的核心模块,它通过清晰的类层次结构和丰富的工具函数,为开发者提供了一套完整的日历数据处理方案。以下是对本专题核心知识点的系统总结。
1. 模块定位: calendar与datetime、time共同构成Python的日期时间工具体系。calendar负责宏观的日历展示和日期周期性计算,datetime专注于精确的日期时间对象操作,time提供底层时间戳和系统时间接口。三者各司其职,在复杂应用场景中经常配合使用。
2. 基础函数速查: month()/prmonth()生成单月文本月历,calendar()/prcal()生成全年文本年历,isleap()判断闰年,leapdays()计算年份区间内的闰年数,weekday()计算星期索引,monthrange()返回当月第一天星期和总天数,day_name/month_name提供星期和月份的名称常量。
3. 类继承体系: Calendar(基类,提供日期迭代器)→ TextCalendar(文本日历输出)和HTMLCalendar(HTML日历输出),以及面向本地化的LocalTextCalendar和LocaleHTMLCalendar。基类负责数据生成逻辑,子类负责格式化和渲染,体现了清晰的单一职责和模板方法设计模式。
4. 核心迭代方法: itermonthdates返回datetime.date对象,itermonthdays返回日期号(0表示跨月),itermonthdays2返回(日期号, 星期)元组,itermonthdays3返回(年, 月, 日)元组。对应的列表方法monthdatescalendar、monthdayscalendar、monthdays2calendar按周分组返回列表,便于层级遍历。
5. 实战模式: 工作日计算(itermonthdays2 + 周末过滤)、周期性会议日期生成(Calendar迭代 + nth过滤)、HTML日历Web组件(继承HTMLCalendar覆写formatday)、日期范围边界计算(monthrange + datetime)。这些模式覆盖了从数据分析到Web开发的主要应用场景。
6. 扩展方向: 实际项目中的日历需求往往超出标准库的能力范围。对于复杂的时区转换和精确时间计算,建议使用pytz或zoneinfo模块。对于业务日历(如交易日历、排班日历),通常需要基于Calendar类自定义子类。对于前端交互式日历组件(如日期选择器、事件日历),建议在前端使用专门的JavaScript日历库,后端仅提供数据API接口。
学习建议: calendar模块的函数接口简单易用,适合快速上手;类体系则提供了高度可扩展的架构。日常开发中,最常用的功能是isleap、weekday、monthrange三个基础函数,以及TextCalendar.formatmonth的文本生成能力。深入学习时应重点理解Calendar的迭代器设计思想——它将"数据生成"与"格式渲染"分离,这种设计模式在Python标准库中多处可见(如csv模块的reader/writer分离)。