Table Of Contents

Previous topic

PyMOTW: csv

Next topic

PyMOTW: commands

This Page

PyMOTW: calendar

  • 模块: calendar
  • 目的: 模块实现了面向年/月/星期的日期操作类
  • Python 版本: 1.4+ 但在2.5中有更新

描述

calendar模块定义了一个Calendar类, 封装了一些日期值(比如指定某月或某年的某星期的日期值)的计算. 另外, TextCalendar和HTMLCalendar类提供预先格式化好的输出.

格式化的例子

下面是一个非常简单的利用TextCalendar类及使用其prmonth()方法产生特定月份的格式化文本输出的例子.

import calendar

c = calendar.TextCalendar(calendar.SUNDAY)
c.prmonth(2007, 7)

这里, 我告诉TextCalendar类以Sunday为一星期的开始, 这遵循了美国人的习惯. 但是它默认是以Monday开始的, 这是欧洲人的习惯.

输出看起来是这样的:

$ python PyMOTW/calendar/calendar_textcalendar.py
 July 2007
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

同样时间的HTML输出稍有不同, 但她没有prmonth()函数:

import calendar

c = calendar.HTMLCalendar(calendar.SUNDAY)
print c.formatmonth(2007, 7)

输出结果大致相同.

July 2007

Sun Mon     Tue     Wed     Thu     Fri     Sat
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

你可以看到, 每一个表格单元都具有一个class属性, 它对应于一星期的特定天.

<table border="0" cellpadding="0" cellspacing="0" class="month">
<tr><th colspan="7" class="month">July 2007</th></tr>
<tr><th class="sun">Sun</th><th class="mon">Mon</th><th class="tue">Tue</th><th class="wed">Wed</th><th class="thu">Thu</th><th class="fri">Fri</th><th class="sat">Sat</th></tr>
<tr><td class="sun">1</td><td class="mon">2</td><td class="tue">3</td><td class="wed">4</td><td class="thu">5</td><td class="fri">6</td><td class="sat">7</td></tr>
<tr><td class="sun">8</td><td class="mon">9</td><td class="tue">10</td><td class="wed">11</td><td class="thu">12</td><td class="fri">13</td><td class="sat">14</td></tr>
<tr><td class="sun">15</td><td class="mon">16</td><td class="tue">17</td><td class="wed">18</td><td class="thu">19</td><td class="fri">20</td><td class="sat">21</td></tr>
<tr><td class="sun">22</td><td class="mon">23</td><td class="tue">24</td><td class="wed">25</td><td class="thu">26</td><td class="fri">27</td><td class="sat">28</td></tr>
<tr><td class="sun">29</td><td class="mon">30</td><td class="tue">31</td><td class="noday"> </td><td class="noday"> </td><td class="noday"> </td><td class="noday"> </td></tr>
</table>

如果你想要输出的格式不同于默认的格式, 你可以使用calendar模块计算日期并且将这些数值组织成你给定的星期和月份范围, 剩余的会自动转换. 类Calendar的函数weekheader(), monthcalendar()和yeardays2calendar()都可以用来完成这种任务.

调用yeardays2calendar()可以产生一个”月份 行”列表. 每个列表包含的月份可作为其他的星期列表. 星期是由日期数字(1-31)和星期数字(0-6)组成的元组列表. 如果某天落在月份之外, 那么它的天数字为0.

pprint.pprint(calendar.Calendar(calendar.SUNDAY).yeardays2calendar(2007, 2))

这里, 调用了yeardays2calendar(2007, 2) 返回2007年, 以每行2月组织的数据.

$ python calendar_yeardays2calendar.py
 [[[[(0, 6), (1, 0), (2, 1), (3, 2), (4, 3), (5, 4), (6, 5)],
 [(7, 6), (8, 0), (9, 1), (10, 2), (11, 3), (12, 4), (13, 5)],
 [(14, 6), (15, 0), (16, 1), (17, 2), (18, 3), (19, 4), (20, 5)],
 [(21, 6), (22, 0), (23, 1), (24, 2), (25, 3), (26, 4), (27, 5)],
 [(28, 6), (29, 0), (30, 1), (31, 2), (0, 3), (0, 4), (0, 5)]],
 [[(0, 6), (0, 0), (0, 1), (0, 2), (1, 3), (2, 4), (3, 5)],
 [(4, 6), (5, 0), (6, 1), (7, 2), (8, 3), (9, 4), (10, 5)],
 [(11, 6), (12, 0), (13, 1), (14, 2), (15, 3), (16, 4), (17, 5)],
 [(18, 6), (19, 0), (20, 1), (21, 2), (22, 3), (23, 4), (24, 5)],
 [(25, 6), (26, 0), (27, 1), (28, 2), (0, 3), (0, 4), (0, 5)]]],
 [[[(0, 6), (0, 0), (0, 1), (0, 2), (1, 3), (2, 4), (3, 5)],
 [(4, 6), (5, 0), (6, 1), (7, 2), (8, 3), (9, 4), (10, 5)],
 [(11, 6), (12, 0), (13, 1), (14, 2), (15, 3), (16, 4), (17, 5)],
 [(18, 6), (19, 0), (20, 1), (21, 2), (22, 3), (23, 4), (24, 5)],
 [(25, 6), (26, 0), (27, 1), (28, 2), (29, 3), (30, 4), (31, 5)]],
 [[(1, 6), (2, 0), (3, 1), (4, 2), (5, 3), (6, 4), (7, 5)],
 [(8, 6), (9, 0), (10, 1), (11, 2), (12, 3), (13, 4), (14, 5)],
 [(15, 6), (16, 0), (17, 1), (18, 2), (19, 3), (20, 4), (21, 5)],
 [(22, 6), (23, 0), (24, 1), (25, 2), (26, 3), (27, 4), (28, 5)],
 [(29, 6), (30, 0), (0, 1), (0, 2), (0, 3), (0, 4), (0, 5)]]],
 [[[(0, 6), (0, 0), (1, 1), (2, 2), (3, 3), (4, 4), (5, 5)],
 [(6, 6), (7, 0), (8, 1), (9, 2), (10, 3), (11, 4), (12, 5)],
 [(13, 6), (14, 0), (15, 1), (16, 2), (17, 3), (18, 4), (19, 5)],
 [(20, 6), (21, 0), (22, 1), (23, 2), (24, 3), (25, 4), (26, 5)],
 [(27, 6), (28, 0), (29, 1), (30, 2), (31, 3), (0, 4), (0, 5)]],
 [[(0, 6), (0, 0), (0, 1), (0, 2), (0, 3), (1, 4), (2, 5)],
 [(3, 6), (4, 0), (5, 1), (6, 2), (7, 3), (8, 4), (9, 5)],
 [(10, 6), (11, 0), (12, 1), (13, 2), (14, 3), (15, 4), (16, 5)],
 [(17, 6), (18, 0), (19, 1), (20, 2), (21, 3), (22, 4), (23, 5)],
 [(24, 6), (25, 0), (26, 1), (27, 2), (28, 3), (29, 4), (30, 5)]]],
 [[[(1, 6), (2, 0), (3, 1), (4, 2), (5, 3), (6, 4), (7, 5)],
 [(8, 6), (9, 0), (10, 1), (11, 2), (12, 3), (13, 4), (14, 5)],
 [(15, 6), (16, 0), (17, 1), (18, 2), (19, 3), (20, 4), (21, 5)],
 [(22, 6), (23, 0), (24, 1), (25, 2), (26, 3), (27, 4), (28, 5)],
 [(29, 6), (30, 0), (31, 1), (0, 2), (0, 3), (0, 4), (0, 5)]],
 [[(0, 6), (0, 0), (0, 1), (1, 2), (2, 3), (3, 4), (4, 5)],
 [(5, 6), (6, 0), (7, 1), (8, 2), (9, 3), (10, 4), (11, 5)],
 [(12, 6), (13, 0), (14, 1), (15, 2), (16, 3), (17, 4), (18, 5)],
 [(19, 6), (20, 0), (21, 1), (22, 2), (23, 3), (24, 4), (25, 5)],
 [(26, 6), (27, 0), (28, 1), (29, 2), (30, 3), (31, 4), (0, 5)]]],
 [[[(0, 6), (0, 0), (0, 1), (0, 2), (0, 3), (0, 4), (1, 5)],
 [(2, 6), (3, 0), (4, 1), (5, 2), (6, 3), (7, 4), (8, 5)],
 [(9, 6), (10, 0), (11, 1), (12, 2), (13, 3), (14, 4), (15, 5)],
 [(16, 6), (17, 0), (18, 1), (19, 2), (20, 3), (21, 4), (22, 5)],
 [(23, 6), (24, 0), (25, 1), (26, 2), (27, 3), (28, 4), (29, 5)],
 [(30, 6), (0, 0), (0, 1), (0, 2), (0, 3), (0, 4), (0, 5)]],
 [[(0, 6), (1, 0), (2, 1), (3, 2), (4, 3), (5, 4), (6, 5)],
 [(7, 6), (8, 0), (9, 1), (10, 2), (11, 3), (12, 4), (13, 5)],
 [(14, 6), (15, 0), (16, 1), (17, 2), (18, 3), (19, 4), (20, 5)],
 [(21, 6), (22, 0), (23, 1), (24, 2), (25, 3), (26, 4), (27, 5)],
 [(28, 6), (29, 0), (30, 1), (31, 2), (0, 3), (0, 4), (0, 5)]]],
 [[[(0, 6), (0, 0), (0, 1), (0, 2), (1, 3), (2, 4), (3, 5)],
 [(4, 6), (5, 0), (6, 1), (7, 2), (8, 3), (9, 4), (10, 5)],
 [(11, 6), (12, 0), (13, 1), (14, 2), (15, 3), (16, 4), (17, 5)],
 [(18, 6), (19, 0), (20, 1), (21, 2), (22, 3), (23, 4), (24, 5)],
 [(25, 6), (26, 0), (27, 1), (28, 2), (29, 3), (30, 4), (0, 5)]],
 [[(0, 6), (0, 0), (0, 1), (0, 2), (0, 3), (0, 4), (1, 5)],
 [(2, 6), (3, 0), (4, 1), (5, 2), (6, 3), (7, 4), (8, 5)],
 [(9, 6), (10, 0), (11, 1), (12, 2), (13, 3), (14, 4), (15, 5)],
 [(16, 6), (17, 0), (18, 1), (19, 2), (20, 3), (21, 4), (22, 5)],
 [(23, 6), (24, 0), (25, 1), (26, 2), (27, 3), (28, 4), (29, 5)],
 [(30, 6), (31, 0), (0, 1), (0, 2), (0, 3), (0, 4), (0, 5)]]]]

这等价于使用formatyear()函数获得的数据

print calendar.TextCalendar(calendar.SUNDAY).formatyear(2007, 2, 1, 1, 2)

以相同的参数值传入, 其输出结果:

$ python ./calendar_formatyear.py
 2007

 January February
Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
 1 2 3 4 5 6 1 2 3
 7 8 9 10 11 12 13 4 5 6 7 8 9 10
14 15 16 17 18 19 20 11 12 13 14 15 16 17
21 22 23 24 25 26 27 18 19 20 21 22 23 24
28 29 30 31 25 26 27 28

 March April
Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
 1 2 3 1 2 3 4 5 6 7
 4 5 6 7 8 9 10 8 9 10 11 12 13 14
11 12 13 14 15 16 17 15 16 17 18 19 20 21
18 19 20 21 22 23 24 22 23 24 25 26 27 28
25 26 27 28 29 30 31 29 30

 May June
Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
 1 2 3 4 5 1 2
 6 7 8 9 10 11 12 3 4 5 6 7 8 9
13 14 15 16 17 18 19 10 11 12 13 14 15 16
20 21 22 23 24 25 26 17 18 19 20 21 22 23
27 28 29 30 31 24 25 26 27 28 29 30

 July August
Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
 1 2 3 4 5 6 7 1 2 3 4
 8 9 10 11 12 13 14 5 6 7 8 9 10 11
15 16 17 18 19 20 21 12 13 14 15 16 17 18
22 23 24 25 26 27 28 19 20 21 22 23 24 25
29 30 31 26 27 28 29 30 31

 September October
Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
 1 1 2 3 4 5 6
 2 3 4 5 6 7 8 7 8 9 10 11 12 13
 9 10 11 12 13 14 15 14 15 16 17 18 19 20
16 17 18 19 20 21 22 21 22 23 24 25 26 27
23 24 25 26 27 28 29 28 29 30 31
30

 November December
Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
 1 2 3 1
 4 5 6 7 8 9 10 2 3 4 5 6 7 8
11 12 13 14 15 16 17 9 10 11 12 13 14 15
18 19 20 21 22 23 24 16 17 18 19 20 21 22
25 26 27 28 29 30 23 24 25 26 27 28 29
30 31

如果你由于某些原因(如想在HTML输出中包含一些链接)需要自己组织输出格式, 你可以使用day_name, day_abbr, month_name, 和month_abbr这些模块属性. 它们可以为当前环境自动配置正确.

计算例子

虽然calendar模块大部分关注日历的不同格式的输出, 但它也提供了一些使用其他方式处理日期的函数, 如计算用于循环事件中的日期. 例如, Python Atlanta User’s Group 在每个月的第一个星期四会面. 为了计算一年的所有会面日期, 你可以使用monthcalendar().

pprint.pprint(calendar.monthcalendar(2007, 7))

注意这里某些天的数字是0. 这是由于这个月的星期中的某些天和其他月中的重叠了.

 $ python calendar_monthcalendar.py
[[0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0]]

记住, 默认情况下, 星期是以Monday作为一星期的开始, 这可以通过函数setfirstweekday()来改变. 另一方面, 由于calendar模块包含了一些用于在日期范围(由monthcalendar()返回得到)中进行定位的常量, 在这个例子中直接跳过会更加方便.

为了计算PyATL在2007年的会面日期, 假设是每个月的第二个星期四, 我们可以使用0值来表明第一个星期的星期二是否被包含在某月中(如果某个月是以星期五开始的, 那么对应的这周中的星期四的值为0).

import calendar

# Show every month
for month in range(1, 13):

    # Compute the dates for each week which overlaps the month
    c = calendar.monthcalendar(2007, month)
    first_week = c[0]
    second_week = c[1]
    third_week = c[2]

    # If there is a Thursday in the first week, the second Thursday
    # is in the second week. Otherwise the second Thursday must
    # be in the third week.
    if first_week[calendar.THURSDAY]:
        meeting_date = second_week[calendar.THURSDAY]
    else:
        meeting_date = third_week[calendar.THURSDAY]

    print '%3s: %2s' % (month, meeting_date)

可以得到PyATL的会面日期为:

$ python calendar_secondthursday.py
1: 11
2: 8
3: 8
4: 12
5: 10
6: 14
7: 12
8: 9
9: 13
10: 11
11: 8
12: 13