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