カレンダー出力
ちょっと HTML でカレンダーつくる必要に迫られたのだけれども、手打ちすると td タグの海の中に誤りが混入しそうな気がしたので(弱気すぎるだろ、オレ)。ここは半自動生成したいなと思った。なにか作っておけば、もし翌月の分を作る時、楽ができるという副作用もあるはず。
ただし、すぐ作れるかどうかは重要。手打ちすればすぐなのだから、1日仕事になってしまうならばダメだ。理想は HTML 手打ちしたのと変わらない速度で HTML 吐くスクリプトが出来上がること。
とりあえず、 0 から作るのは避けてなんかさがす。いや、思い出す。
Python にはカレンダー関連を面倒見てくれる標準ライブラリ calendar モジュールがある。コード読解に 15 分。だいたいつかんだので、 Calendar クラスを希望の形に拡張してみる。こんなかんじか?
コード
# coding: utf-8 import calendar class SpamCalendar(calendar.Calendar): weekday = (u'月', u'火', u'水', u'木', u'金', u'土', u'日') def __init__(self, event, firstweekday=0): self.event = event super(SpamCalendar, self).__init__(firstweekday) def formatweekday(self, theday): return u'<td>%s</td>' % self.weekday[theday] def formatweekheader(self): s = u''.join(self.formatweekday(i) for i in self.iterweekdays()) return u'<tr>%s</tr>' % s def formatday(self, theday, theweekday): if theday == 0: return u'<td> </td>' else: return '<td>%d</td>' % theday def formatweek(self, theweek): s = u''.join(self.formatday(d, wd) for d, wd in theweek) return u'<tr>%s</tr>' % s def formateventday(self, theday, theweekday): if theday == 0: return u'<td> </td>' else: event = u'<br />'.join(self.event.get(theday, [u' '])) return u'<td>%s</td>' % event def formatweekevent(self, week): s = u''.join(self.formateventday(d, wd) for d, wd in week) return u'<tr>%s</tr>' % s def formatmonth(self, year, month): v = [] a = v.append a(u'<table class="month">') a(u'\n') a(self.formatweekheader()) a(u'\n') for week in self.monthdays2calendar(year, month): a(self.formatweek(week)) a(self.formatweekevent(week)) a(u'\n') a(u'</table>') return u''.join(v) def main(): event_one = u'1のつく日' event_first = u'月始め' event = { 1: [event_one, event_first], 11: [event_one], 21: [event_one], } cal = SpamCalendar(event, 6) print cal.formatmonth(2009, 11) if __name__ == '__main__': main()
20分弱…完成! 実行してみる。
出力
日 | 月 | 火 | 水 | 木 | 金 | 土 |
1 | 2 | 3 | 4 | 5 | 6 | 7 |
1のつく日 月始め | ||||||
8 | 9 | 10 | 11 | 12 | 13 | 14 |
1のつく日 | ||||||
15 | 16 | 17 | 18 | 19 | 20 | 21 |
1のつく日 | ||||||
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | |||||
内容はあっている。が、希望のものとは少し違う。イベント列は2列欲しい。もうすこし手直しがいるみたい。できあがったら CSS で飾ればいける、かな。とりあえず table.month td に width と height の指定は要りそう。