Pythonのカレンダーモジュールを用いる
Pythonにはカレンダーに関する処理を行うのに便利なcalendarというモジュールがある。
(2015/1/25)以前は2ページに分けて公開していたが、このページに統合した。リファレンスのリンク先も修正し、サンプルコードについてもPython 3で動作することなどを目的に一部修正した。
- カレンダーとしての内部の処理を利用するのに適したcalndar.Calendarクラス
- 整形表示を容易に行うためのクラス
- calendar.Calendarクラスを用いた例
- calendar.TextCalendarクラスを用いた例
- calendar.HTMLCalendarクラスを用いた例
カレンダーとしての内部の処理を利用するのに適したcalndar.Calendarクラス
calndar.Calendarクラスのオブジェクトを作成し、メンバ関数itermonthdates()に西暦年と月を指定するとジェネレータオブジェクト(関連記事)が得られる。>>> import calendar >>> c = calendar.Calendar () >>> g = c.itermonthdates (2010, 6) >>> g <generator object itermonthdates at 0xXXXXXXXXXXXX>
「次に進める」処理を繰り返しながら得られるオブジェクト(datetime.dateオブジェクト)は指定した前の月の最後の週の最初の曜日(既定では月曜)の日から始まり、指定された月の全ての日が得られた後、次の月の最初の週の最後の曜日(既定では日曜)の日で終わる。この形により、どの日が何曜日なのかが分かるようになっている。
(前の月の最後の月曜(最初の曜日)) >>> g.next () datetime.date (2010, 5, 31) (以下同様に続いていく) >>> g.next () datetime.date (2010, 6, 1) >>> g.next () datetime.date (2010, 6, 2) ... >>> g.next () datetime.date (2010, 6, 30) >>> g.next () datetime.date (2010, 7, 1) >>> g.next () datetime.date (2010, 7, 2) >>> g.next () datetime.date (2010, 7, 3) (次の月の最初の日曜(最後の曜日)) >>> g.next () datetime.date (2010, 7, 4) (最後に到達してStopIteration例外が発生) >>> g.next () Traceback (most recent call last): File "<stdin>", line 1, in <module> StopIteration
実際としてはenumerate()を同時に用いてループをする形が便利。
for i, d in enumerate (c.itermonthdates ([西暦年], [月])): # ここに表示などの処理を記述 # 「i % 7」の値によってその日の曜日が分かる # d.monthの値がitermonthdates()に指定したものと一致すればその月 # 異なれば前の月の最後か次の月の最初のどちらか
開始曜日の変更
calndar.Calendarクラスと後述の派生クラスでは週の開始の曜日を月曜としているが、コンストラクタ引数により変更することができる(月曜が0,日曜が6)。(日曜を週の始まりとする) c = calendar.Calendar (6)
整形表示を容易に行うためのクラス
バージョン2.5以上のPythonではcalコマンドのような整形済みテキストを出力するcalndar.TextCalendarクラスとHTMLソース(テーブルを使用)を出力するcalndar.HTMLCalendarクラスが用意されている。いずれもメンバ関数formatmonth()に西暦年と月を指定することで文字列オブジェクトとして結果を得る形となる。calendar.Calendarクラスを用いた例
この例では、指定された年/月の日付と曜日を順に出力し、前後の月の日は「---」付きで出力する。開始の曜日を日曜としたものと月曜としたものの2つのバージョンを続けて出力する(以下の例について全て同様)。[任意]ファイル名: calendartest.py
#! /usr/bin/python # -*- coding: utf-8 -*- # 指定された年/月の日付と対応する曜日を出力 from __future__ import print_function import calendar import sys if len (sys.argv) != 3: sys.exit ('USAGE: {0} [year] [month]'.format (sys.argv[0])) year = month = None try: year = int (sys.argv[1]) except ValueError: # 数値でない文字列の場合 sys.exit ('ERROR: invalid year ({0})'.format (sys.argv[1])) try: month = int (sys.argv[2]) except ValueError: sys.exit ('ERROR: invalid month ({0})'.format (sys.argv[2])) # もし不正な月が指定されると後でValueErrorが発生する # 今回はここで値をチェックしておくことにする if month > 12 or month < 1: sys.exit ('ERROR: invalid month ({0})'.format (month)) # 内部的に日曜からのカレンダーで処理する場合 c = calendar.Calendar (6) # 6を指定すると日曜から開始 wday = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'] for i, d in enumerate (c.itermonthdates (year, month)): if d.month == month: print ('{0}/{1} {2}'.format (d.month, d.day, wday[i % 7])) else: print ('--- {0}/{1} {2} ---'.format (d.month, d.day, wday[i % 7])) print ('-' * 80) # 内部的に月曜からのカレンダーで処理する場合 c = calendar.Calendar () # 開始曜日の既定値は0(月曜) wday = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'] for i, d in enumerate (c.itermonthdates (year, month)): if d.month == month: print ('{0}/{1} {2}'.format (d.month, d.day, wday[i % 7])) else: print ('--- {0}/{1} {2} ---'.format (d.month, d.day, wday[i % 7]))
下は実行例。
$ [calendartest.pyの場所] 2010 6 --- 5/30 Sun --- --- 5/31 Mon --- 6/1 Tue 6/2 Wed 6/3 Thu 6/4 Fri 6/5 Sat 6/6 Sun 6/7 Mon 6/8 Tue 6/9 Wed 6/10 Thu 6/11 Fri 6/12 Sat 6/13 Sun 6/14 Mon 6/15 Tue 6/16 Wed 6/17 Thu 6/18 Fri 6/19 Sat 6/20 Sun 6/21 Mon 6/22 Tue 6/23 Wed 6/24 Thu 6/25 Fri 6/26 Sat 6/27 Sun 6/28 Mon 6/29 Tue 6/30 Wed --- 7/1 Thu --- --- 7/2 Fri --- --- 7/3 Sat --- -------------------------------------------------------------------------------- --- 5/31 Mon --- 6/1 Tue 6/2 Wed 6/3 Thu 6/4 Fri 6/5 Sat 6/6 Sun 6/7 Mon 6/8 Tue 6/9 Wed 6/10 Thu 6/11 Fri 6/12 Sat 6/13 Sun 6/14 Mon 6/15 Tue 6/16 Wed 6/17 Thu 6/18 Fri 6/19 Sat 6/20 Sun 6/21 Mon 6/22 Tue 6/23 Wed 6/24 Thu 6/25 Fri 6/26 Sat 6/27 Sun 6/28 Mon 6/29 Tue 6/30 Wed --- 7/1 Thu --- --- 7/2 Fri --- --- 7/3 Sat --- --- 7/4 Sun ---
calendar.TextCalendarクラスを用いた例
この例では、指定された年/月の整形済みカレンダー(テキスト形式)を出力する。[任意]ファイル名: textcalendartest.py
#! /usr/bin/python # -*- coding: utf-8 -*- # 指定された年/月の整形済みカレンダーを出力(calコマンドに近い形) from __future__ import print_function import calendar import sys # 下のコメントを解除してロケールを設定すると表記が日本語になるが # 表示に問題がある場合がある #import locale; locale.setlocale (locale.LC_ALL, '') if len (sys.argv) != 3: sys.exit ('USAGE: {0} [year] [month]'.format (sys.argv[0])) year = month = None try: year = int (sys.argv[1]) except ValueError: # 数値でない文字列の場合 sys.exit ('ERROR: invalid year ({0})'.format (sys.argv[1])) try: month = int (sys.argv[2]) except ValueError: sys.exit ('ERROR: invalid month ({0})'.format (sys.argv[2])) # もし不正な月が指定されると後でValueErrorが発生する # 今回はここで値をチェックしておくことにする if month > 12 or month < 1: sys.exit ('ERROR: invalid month ({0})'.format (month)) # 内部的に日曜からのカレンダーで処理する場合 tc = calendar.TextCalendar (6) # 「6」を指定すると日曜から開始 print (tc.formatmonth (year, month)) #print (tc.formatyear (year)) # 年全体 print ('-' * 80) # 内部的に月曜からのカレンダーで処理する場合 tc = calendar.TextCalendar () # 開始曜日の既定値は0(月曜) print (tc.formatmonth (year, month)) #print (tc.formatyear (year))
下は実行例。
$ [textcalendartest.pyの場所] 2010 6 June 2010 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 -------------------------------------------------------------------------------- June 2010 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
calendar.HTMLCalendarクラスを用いた例
この例では、指定された年/月の整形済みHTMLカレンダーのソースを出力する。[任意]ファイル名: htmlcalendartest.py
#! /usr/bin/python # -*- coding: utf-8 -*- # 指定された年/月の整形済みHTMLカレンダーを出力 from __future__ import print_function import calendar import sys # 下のコメントを解除してロケールを設定すると表記が日本語になる #import locale; locale.setlocale (locale.LC_ALL, '') if len (sys.argv) != 3: sys.exit ('USAGE: {0} [year] [month]'.format (sys.argv[0])) year = month = None try: year = int (sys.argv[1]) except ValueError: # 数値でない文字列の場合 sys.exit ('ERROR: invalid year ({0})'.format (sys.argv[1])) try: month = int (sys.argv[2]) except ValueError: sys.exit ('ERROR: invalid month ({0})'.format (sys.argv[2])) # もし不正な月が指定されると後でValueErrorが発生する # 今回はここで値をチェックしておくことにする if month > 12 or month < 1: sys.exit ('ERROR: invalid month ({0})'.format (month)) # 内部的に日曜からのカレンダーで処理する場合 hc = calendar.HTMLCalendar (6) # 「6」を指定すると日曜から開始 print (hc.formatmonth (year, month)) #print (hc.formatyear (year)) # 年全体 print ('-' * 80) # 内部的に月曜からのカレンダーで処理する場合 hc = calendar.HTMLCalendar () # 開始曜日の既定値は0(月曜) print (hc.formatmonth (year, month)) #print (hc.formatyear (year))
2010年6月の実行例は下のようになる。
(1つ目/日曜日から土曜日)
June 2010 | ||||||
---|---|---|---|---|---|---|
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 |
(2つ目/月曜日から日曜日)
June 2010 | ||||||
---|---|---|---|---|---|---|
Mon | Tue | Wed | Thu | Fri | Sat | Sun |
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 |
参考URL:
使用したバージョン:
- Python 2.6.4, 2.7.8, 3.4.2