calendar -- 日历相关│Python标准库

前情提示: 测试代码中,右尖括号(>)表示命令行中输入的命令; 单独一行并以井字符(#)开头的为输出内容; 库的导入仅在本文的第一个测试代码中展现,其他代码块均省略库的导入代码。

  • 系统类型: Windows 10
  • python 版本: Python 3.9.0

calendar 模块提供了与日历有关的函数与类。其中既包含了可方便用于计算或信息处理的日历格式,也包含了可直观展示的日历格式,甚至有用于网页展示的 html 格式.

calendar 模块提供了三个类,也提供了一些属性和函数进行快捷操作。calendar 模块提供的函数将分布在同功能的类中介绍。

calendar 模块提供了 4 个属性,所有属性返回的数据都是可迭代对象:

  • calendar.day_name : 在当前语言环境下表示星期几的数组
  • calendar.day_abbr : 在当前语言环境下表示星期几缩写的数组
  • calendar.month_name : 在当前语言环境下表示一年中月份的数组。这里为了现实习惯,一月的月号为 1,所以此数组的元素个数为 13 个,其中索引值为 0 的元素的值为空
  • calendar.month_abbr : 在当前语言环境下表示月份简写的数组。这里为了现实习惯,一月的月号为 1,所以此数组的元素个数为 13 个,其中索引值为 0 的元素的值为空
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']

Calendar 类

class calendar.Calendar(firstweekday=0)
参数:
    firstweekday: int, 指定一周的第一天, 0 表示星期一, 6 表示星期天, 默认为 0

创建已 Calendar 对象,Calendar 对象提供了一些方法,这些方法可以用于各种场景的与日历有关的数据,得到的数据并不便于查看,但方便计算。

iterweekdays()
iterweekdays()
返回值:
    可迭代对象

返回一个可迭代对象,包含一星期对应的枚举值,排序在第一个元素的枚举值与类参数 firstweekday 的值一致。

import calendar

cc = calendar.Calendar(1)
print(list(cc.iterweekdays()))
# [1, 2, 3, 4, 5, 6, 0]

cc = calendar.Calendar(4)
print(list(cc.iterweekdays()))
# [4, 5, 6, 0, 1, 2, 3]

PS: 无论一周的第一天设置为星期几,这与七天中每天对应的枚举值无关。星期一的枚举值一定是 0,星期二的枚举值一定是 1,以此类推,星期天的枚举值一定是 6

itermonthdates()
itermonthdates(year, month)
参数:
    year: 年
    month: 月
返回值:
    可迭代对象

返回一个可迭代对象,包含某年某月当月的全部日期,日期对象为 datetime 对象。

若本月月初和月末不是一个完整的周,也会返回其他月份的日期用于组成一个完整的日期。也就是说某一周的日期里,包含指定月份的日期,也包含其他月份的日期,那么本方法返回的日期中也包含这些在同一周内的其他月份的日期。

cc = calendar.Calendar(0)
print(list(cc.itermonthdates(2021, 1)))
# [
# datetime.date(2020, 12, 28), datetime.date(2020, 12, 29),
# datetime.date(2020, 12, 30), datetime.date(2020, 12, 31),
# datetime.date(2021, 1, 1), datetime.date(2021, 1, 2),
# ......
# datetime.date(2021, 1, 30), datetime.date(2021, 1, 31)
# ]

PS: 此模块的一些方法返回值内容过多,此文章将会省略一部分返回内容。

itermonthdays()
itermonthdays(year, month)
itermonthdays2(year, month)
itermonthdays3(year, month)
itermonthdays4(year, month)
参数:
    year: 年
    month: 月
返回值:
    可迭代对象

本方法是四胞胎兄弟,它们都返回一个可迭代对象,包含某年某月当月的全部日期。但是它们返回的元素的内容却不尽相同。

它们与 itermonthdates() 函数类似,在返回的日期中,月初和月末那一周种同周不同月的日期也会展出出来,但是与 itermonthdates() 函数不同的是,不在指定月份的日期对象展示的日期的值是 0

itermonthdays() 函数,可称呼为一号函数,可迭代对象的元素为日期对应的天数。

itermonthdays2() 函数,可称呼为二号函数,可迭代对象的元素为由日期对应的天数和当天星期几的枚举值组成的元组。例如: (1, 5) 表示本月的一号,星期五。

itermonthdays3() 函数,可称呼为三号函数,可迭代对象的元素为由年、月、日组成的元组。例如: (2021, 1, 1) 表示2021年1月1日。

itermonthdays4() 函数,可称呼为四号函数,可迭代对象的元素为由年、月、日和当天星期表示的枚举值组成的元组。例如: (2021, 1, 1, 5) 表示2021年1月1日周六。

cc = calendar.Calendar(0)
'''一号函数'''
print(list(cc.itermonthdays(2021, 1)))
# [0, 0, 0, 0, 1, 2, ......, 30, 31]

'''二号函数'''
print(list(cc.itermonthdays2(2021, 1)))
# [(0, 0), (0, 1), (0, 2), (0, 3), (1, 4), (2, 5), ......, (30, 5), (31, 6)]

'''三号函数'''
print(list(cc.itermonthdays3(2021, 1)))
# [(2020, 12, 28), (2020, 12, 29), (2020, 12, 30), (2020, 12, 31), (2021, 1, 1),
#  (2021, 1, 2), (2021, 1, 3), (2021, 1, 4), (2021, 1, 5),
# ......
#  (2021, 1, 28), (2021, 1, 29), (2021, 1, 30), (2021, 1, 31)]

'''四号函数'''
print(list(cc.itermonthdays4(2021, 1)))
# [(2020, 12, 28, 0), (2020, 12, 29, 1), (2020, 12, 30, 2),
#  (2020, 12, 31, 3), (2021, 1, 1, 4), (2021, 1, 2, 5),
# ......
#  (2021, 1, 29, 4), (2021, 1, 30, 5), (2021, 1, 31, 6)]
获取指定年月的周列表
monthdatescalendar(year, month)
monthdays2calendar(year, month)
monthdayscalendar(year, month)
参数:
    year: 年
    month: 月
返回值:
    列表, 一个多维列表

以上三个函数都返回指定年月的日期数据,所返回的数据是一个列表,在列表内部,列表的元素是以周为单位分割的子列表,子列表中的元素才是日期数据。

以上三个函数的不同点就在子列表中的日期数据:

monthdatescalendar() 函数可以简称为 日期数据函数,因为这个函数的返回值内的日期数据是以 datetime.date 对象展示的。

monthdayscalendar() 函数可以简称为 一号函数,这个函数的返回值内的日期数据是以代表日期的数字的形式展示的。

monthdays2calendar() 函数可以简称为 二号函数,这个函数的返回值内的日期数据是以代表日期的数字和当天星期表示的枚举值组成的二元元组的形式展示的。

一号函数二号函数 中,如果某个日期数据不是指定年月内的日期,那么代表日期的数字将是 0

cc = calendar.Calendar(0)

'''返回 datetime.date'''
print(cc.monthdatescalendar(2021, 1))
# [
#   [datetime.date(2020, 12, 28), ......, datetime.date(2021, 1, 3)],
#   ......
#   [datetime.date(2021, 1, 25), ......, datetime.date(2021, 1, 31)]
# ]

'''返回日期代表的数字'''
print(cc.monthdayscalendar(2021, 1))
# [
#   [0, 0, 0, 0, 1, 2, 3], ......, [25, 26, 27, 28, 29, 30, 31]
# ]

'''返回日期代表的数字与当天星期表示的枚举值组成的二元元组'''
print(cc.monthdays2calendar(2021, 1))
# [
#   [(0, 0), (0, 1), (0, 2), (0, 3), (1, 4), (2, 5), (3, 6)],
#   ......
#   [(25, 0), (26, 1), (27, 2), (28, 3), (29, 4), (30, 5), (31, 6)]
# ]

calendar 模块中,calendar.monthcalendar(year, month) 快捷函数与 monthdayscalendar() 方法类似,返回值相同。

获取可用于格式化的指定年的数据

yeardatescalendar(year, width=3)
yeardayscalendar(year, width=3)
yeardays2calendar(year, width=3)
参数:
    year: 年
    width: 关键字参数, 每几个月分为一组, 默认为 3
返回值:
    列表, 多维列表

返回一个多维列表,列表内容为指定年的日期数据。列表的元素是以参数 width 设定的月份分组,指定数量的月份为一组,所以列表的元素个数就是分组个数,为了方便区分多维度(层级)的列表,我们可以将整个列表称为 年列表年列表 下代表月份分组的子列表称为 月分组子列表。当前格式为: [[月分组子列表], ......, [月分组子列表]]

月分组子列表 的元素就是属于本组的月份,月份数据格式也是列表,可以称为 月子列表月分组子列表 格式为: [[月子列表], ......, [月子列表]]

月子列表 的元素是属于本月的周,周的数据格式依旧是列表,可以称为 周子列表月子列表 格式为: [[周子列表], ......, [月子列表]]

对于三个函数而言,以上部分数据格式都相同,三个函数不同的就是 周子列表 中的元素,没错,就是日期数据。这里的 周子列表 中的周数据也是秉承着 Calendar 类的特定,属于本周但是不属于本月的日期也会展示,但是若是展示日期代表的数字时,会展示为 0

yeardatescalendar() 函数返回值中的日期数据格式为 datetime.date 对象格式。yeardayscalendar() 函数返回值中日期数据为日期代表的数字。 yeardays2calendar() 函数返回值中日期数据为日期代表的数字与当天星期表示的枚举值组成的二元元组。

'''备注: 返回数据过于庞大, 受限于篇幅, 测试示例中仅具体展示了列表格式'''
cc = calendar.Calendar(0)

'''日期数据为日期代表的数字'''
print(cc.yeardayscalendar(2021, width=2))
# [
#     [
#         [
#             [0, 0, 0, 0, 1, 2, 3], ......, [25, 26, 27, 28, 29, 30, 31],
#         ],
#         [
#             [1, 2, 3, 4, 5, 6, 7], ......, [22, 23, 24, 25, 26, 27, 28],
#         ],
#     ],
#     ......,
#     [
#         [
#             [1, 2, 3, 4, 5, 6, 7], ......, [29, 30, 0, 0, 0, 0, 0],
#         ],
#         [
#             [0, 0, 1, 2, 3, 4, 5], ......, [27, 28, 29, 30, 31, 0, 0],
#         ],
#     ],
# ]

'''日期数据为是以代表日期的数字和当天星期表示的枚举值组成的二元元组'''
print(cc.yeardays2calendar(2021, width=2))
# [
#     [
#         [
#             [(0, 0), ......, (3, 6)], ......, [(25, 0), ......, (31, 6)],
#         ],
#         [
#             [(1, 0), ......, (7, 6)], ......, [(22, 0), ......, (28, 6)],
#         ],
#     ],
#     ......,
#     [
#         [
#             [(1, 0), ......, (7, 6)], ......, [(29, 0), ......, (0, 6)],
#         ],
#         [
#             [(0, 0), ......, (5, 6)], ......, [(27, 0), ......, (0, 6)],
#         ],
#     ],
# ]

'''日期数据为 datatime.data 对象'''
print(cc.yeardatescalendar(2021, width=2))
# [
#     [
#         [
#             [datetime.date(2020, 12, 28), ......, datetime.date(2021, 1, 3),],
#             ......,
#             [datetime.date(2021, 1, 25), ......, datetime.date(2021, 1, 31),],
#         ],
#         [
#             [datetime.date(2021, 2, 1)), ......, datetime.date(2021, 2, 7),],
#             ......,
#             [datetime.date(2021, 2, 22), ......, datetime.date(2021, 2, 28),],
#         ],
#     ],
#     ......,
#     [
#         [
#             [datetime.date(2021, 11, 1), ......, datetime.date(2021, 11, 7),],
#             ......,
#             [datetime.date(2021, 11, 29), ......, datetime.date(2021, 12, 5),],
#         ],
#         [
#             [datetime.date(2021, 11, 29), ......, datetime.date(2021, 12, 5),],
#             ......,
#             [datetime.date(2021, 12, 27), ......, datetime.date(2022, 1, 2),],
#         ],
#     ],
# ]

TextCalendar 类

class calendar.TextCalendar(firstweekday=0)
参数:
    firstweekday: int, 指定一周的第一天, 0 表示星期一, 6 表示星期天, 默认为 0

TextCalendar 实例化对象,可通过 TextCalendar 实例化对象提供的方法获取纯文本的日历数据,通常用于查看,无法用于计算。

获取一个月的日历数据
formatmonth(theyear, themonth, w=0, l=0)
prmonth(theyear, themonth, w=0, l=0)
参数
    theyear: 年份
    themonth: 月份
    w: 日期宽度, 日期内容始终为居中
    l: 每星期占用的行数

formatmonth() 函数与 prmonth() 函数的目的都是给出指定年月当月的日历数据,但是 formatmonth() 函数是以返回值的方式反馈的,prmonth() 函数则是直接打印数据。

tc = calendar.TextCalendar(0)

'''返回值'''
print(tc.formatmonth(2021, 1))
#     January 2021
# 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

'''直接打印'''
tc.prmonth(2021, 1)
#     January 2021
# 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 模块的快捷函数中,calendar.prmonth(theyear, themonth, w=0, l=0)prmonth() 方法相同,都是直接打印出整个月的日历; 另一个快捷函数 calendar.month(theyear, themonth, w=0, l=0)formatmonth() 方法相同,是返回指定月份的日历。

获取一年的日历数据
formatyear(theyear, w=2, l=1, c=6, m=3)
pryear(theyear, w=2, l=1, c=6, m=3)
参数:
    theyear: 年份
    w: 日期宽度, 日期内容始终为居中
    l: 每星期占用的行数
    c: 月与月之间的间隔大小
    m: 每列可展示多少个月份

formatyear() 函数与 pryear() 函数的目的都是给出指定年的日历数据,但是 formatyear() 函数是以返回值的方式反馈的,pryear() 函数则是直接打印数据。

年日历数据格式可以看做是 12 个月日历数据的汇总,因篇幅原因就不展示测试示例了。

同获取指定月份日历数据的两个方法一样,获取指定年份的日历数据也有两个对应的快捷函数,calendar.prcal(year, w=0, l=0, c=6, m=3) 快捷函数对应 pryear() 方法,calendar.calendar(year, w=2, l=1, c=6, m=3) 快捷函数对应 formatyear() 方法。

HTMLCalendar 类

class calendar.HTMLCalendar(firstweekday=0)
参数:
    firstweekday: int, 指定一周的第一天, 0 表示星期一, 6 表示星期天, 默认为 0

HTMLCalendar 实例化对象,可以通过 HTMLCalendar 实例化对象提供的方法生成可以在网页中展示的 HTML 日历。并且也提供了一些属性来修改各种标签的类名,便于修改样式。

formatmonth() 方法获取一个展示指定月份日历的 HTML 表格。

formatmonth(theyear, themonth, withyear=True)
参数:
    theyear: 年
    themonth: 月
    withyear: 布尔值, 默认为 True, 若为 True, 则表头内容会包含年份, 否则不包含
返回值:
    str, 一个 table 标签, 包含指定月份日历数据

formatyear() 方法获取一个展示指定年份日历的 HTML 表格。

formatyear(theyear, width=3)
参数:
    theyear: 年
    width: 默认值为 3, 表示一行可显示的月份数量
返回值:
    str, 一个 table 标签, 包含指定年份日历数据

formatyearpage() 方法返回一个完整的 HTML 页面,其中主要内容就是指定年份日历数据。

formatyearpage(theyear, width=3, css='calendar.css', encoding=None)
参数:
    theyear: 年
    width: 默认值为 3, 表示一行可显示的月份数量
    css: 导入的 css 文件, 用于丰富日历表样式
    encoding: 编码, 若为 None 则使用系统默认编码
返回值:
    str, 一个完整的 HTML 页面代码

使用以上方法生成的 HTML 代码中,每个标签都会有 class 属性,这些 class 属性是系统默认的,可能会对项目产生冲突或者命名规则不匹配等情况,HTMLCalendar 类给出了一系列可修改属性来改变这些标签上的 class 属性。

  • cssclasses : 对应星期一到星期天的 class 名称列表,列表元素必须有 7 个,默认为: ["mon", "tue", "wed", "thu", "fri", "sat", "sun"]
  • cssclass_noday : 在某周内,某日期在上月或下月时,此日期 td 标签的 class
  • cssclasses_weekday_head : 正常日期的 td 标签的 class,默认为当前日期代表的星期几对应的 class 名。
  • cssclass_month_head: 月历的表头 class,默认为 month
  • cssclass_month : 月历的 table 标签的 class,默认为 month
  • cssclass_year : 年历的 table 标签的 class,默认为 year
  • cssclass_year_head : 年历的表头 class,默认为 year

将以下 css 复制粘贴到某个 css 文件中,并 python 代码,在浏览器中打开生成的 HTML 文件,来查看使用 python 生成的日历。

PS: 此 css 是在网络中寻找的,使用的都是标签名,对 HTMLCalendar 类中 class 相关内容无学习效果。

table {width: 100%;}
table tr th {text-align: center;font-size: 16px;background-color: #316497;color: #99ccff;}
table tr td {width: 10%;border: 1px solid #555;vertical-align: top;height: 120px;padding: 2px;}
td.noday {background-color: #eee;}
td.filled {background-color: #99ccff;}
td.today {border: 4px solid #316497;}
.dayNumber {font-size: 16px !important;font-weight: bold;}
a {font-size: 10px;}

运行以下 python 代码:

hc = calendar.HTMLCalendar(0)

with open('./test.html', 'wb') as f:
    f.write(hc.formatyearpage(2021, css='calendar.css'))

在运行目录下,会生成一个名称为 test.html 的文件,在浏览器打开这个文件即可看到效果。

快捷函数

在类的介绍中,共有 5 个快捷函数与类中的方法含义一致,就直接在对应方法的介绍中说明了,没有注意到的小伙伴可以向上翻阅回顾一下。剩余的快捷函数就留到这里一起介绍吧。

setfirstweekday() 函数设置一周是以周几为起点计算的。设置时可以使用代表星期的常量或者枚举值。

calendar.setfirstweekday(weekday)
参数:
    weekday: 表示星期的常量或枚举值, 枚举值即对应的数字, 星期一到星期日的
             常量则分别为:MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY 和 SUNDAY
返回值:
    None

firstweekday() 函数获取一周的第一天是周几。无论设置时使用的是代表星期的常量还是代表星期的枚举值,返回的一定是枚举值。

calendar.firstweekday()
返回值:
    int, 代表星期的枚举值

isleap() 函数判断指定年是否是闰年,如果是闰年则返回 True,否则返回 False

calendar.isleap(year)
参数:
    year: 年份
返回值:
    布尔值

leapdays() 函数获取某个范围年份(y1y2 年之间)的闰年数量。

calendar.leapdays(y1, y2)
参数:
    y1, y2: 年份
返回值:
    int

weekday() 函数获取某年某月某日是星期几,返回代表星期的枚举值。

calendar.weekday(year, month, day)
参数:
    year: 年
    month: 月
    day: 日
返回值:
    int, 代表星期的枚举值

weekheader() 函数列出所有星期的英文缩写头,可以使用参数 n 来指定缩写单词的字母数量。返回一个字符串,每个英文缩写头以双空格隔开。

calendar.weekheader(n)
参数:
    n: 缩写字母的数量
返回值:
    str, 每个缩写以双空格隔开

monthrange() 函数获取指定年月当月第一天是星期几,并获取当月天数。将两个数据组合成一个元组返回.

calendar.monthrange(year, month)
参数:
    year: 年
    month: 月
返回值:
    二元元组,某月第一天星期对应的枚举值和当月天数组成

参考资料

官方文档: https://docs.python.org/zh-cn/3/library/calendar.html#calendar.HTMLCalendar

源代码: Lib/calendar.py

公众号 : 「python杂货铺」,专注于 python 语言及其相关知识。发掘更多原创文章,期待您的关注。

你可能感兴趣的:(calendar -- 日历相关│Python标准库)