calendar – 日付の処理

目的:calendar モジュールは年/月/週を管理する日付を処理するクラスを実装する
利用できるバージョン:1.4 で追加、2.5 で拡張

calendar モジュールは、特定の月または年のある週の日付といった計算をカプセル化する Calendar クラスを定義します。さらに TextCalendarHTMLCalendar クラスは、フォーマット済みの出力を生成できます。

フォーマットサンプル

TextCalendar を使用して、ある月のフォーマット済みのテキスト出力を生成するには prmonth() メソッドがとても簡単です。

import calendar

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

このサンプルはアメリカの規則に従い、週が日曜日から始まるように TextCalendar を設定します。デフォルトは、週が月曜日から始まるヨーロッパの規則を使用します。

次のような結果になります。

$ python 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)

レンダリングされた HTML 出力は大まかに同じように見えますが、HTML タグで囲まれます。さらにテーブルの各セルは、曜日に対するクラス属性をもちます。

$ python calendar_htmlcalendar.py
<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">&nbsp;</td><td class="noday">&nbsp;</td><td class="noday">&nbsp;</td><td class="noday">&nbsp;</td></tr>
</table>

デフォルトで利用できるフォーマット以外の出力を生成する必要がある場合、 calendar で週と月の範囲に値をセットして日付を計算できます。そして、その実行結果を繰り返し処理できます。 Calendarweekheader(), monthcalendar(), yeardays2calendar() メソッドは、特にそういった処理に便利です。

yeardays2calendar() を呼び出すと、”月の行” のリストのシーケンスを生成します。それぞのリストには、週毎のリストが含まれています。週は日(1-31)と曜日(0-6)で構成されるタプルのリストです。その月に存在しない日は0になります。

import calendar
import pprint

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

yeardays2calendar(2007、2) を呼び出すと、2007年の1行につき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() が使用するデータと同じです。

import calendar

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 アトランタユーザグループは毎月第2木曜日にミーティングを行っています。年間のミーティング日程を計算するには monthcalendar() の返り値を使用できます。

import calendar
import pprint

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

日によっては 0 があることに注目してください。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]]

前節で説明したように週の最初の日は月曜日です。週の最初の曜日は setfirstweekday() を呼び出すことで変更できます。別の方法としては、 calendar モジュールは monthcalendar() が返す日付の範囲にインデクシングするための定数を含むので、この場合はその手順を省略してかなり便利です。

毎月第2木曜日と仮定した 2007 年の PyATL ミーティングの日程を計算するには、その月の最初の週に木曜日が含まれるかどうか(もしくは、月の最初の日が金曜日か等)を調べるのに 0 の値を使用できます。

import calendar

# 全ての月を表示する
for month in range(1, 13):

    # その月と重複するそれぞれの週の日付を計算する
    c = calendar.monthcalendar(2007, month)
    first_week = c[0]
    second_week = c[1]
    third_week = c[2]

    # 最初の週に木曜日がある場合、第2木曜日は2番目の週になる
    # それ以外は第3週にある
    if first_week[calendar.THURSDAY]:
        meeting_date = second_week[calendar.THURSDAY]
    else:
        meeting_date = third_week[calendar.THURSDAY]

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

2007 年の 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

See also

calendar
本モジュールの標準ライブラリドキュメント
time
低レベルの時間関数
datetime
タイムスタンプとタイムゾーンを含む日付を扱う
Bookmark and Share