Python calendarモジュールでカレンダー表示・出力する方法【テキスト・HTML】

Pythonの標準ライブラリcalendarモジュールを使用してカレンダーをテキストやHTML形式で表示・出力する方法を詳しく解説します。基本的な使用方法から応用例まで幅広くカバーします。

calendarモジュールの基本

基本的なカレンダー表示

import calendar

# 2024年1月のカレンダーを表示
year = 2024
month = 1

print(calendar.month(year, month))

年間カレンダーの表示

import calendar

# 2024年の年間カレンダーを表示
year = 2024
print(calendar.calendar(year))

# 幅を指定してカレンダーを表示
print(calendar.calendar(year, w=3, l=2, c=8))

特定の月の情報取得

import calendar

year = 2024
month = 1

# 月の週と曜日の情報を取得
month_calendar = calendar.monthcalendar(year, month)
print("月のカレンダー(2次元リスト):")
for week in month_calendar:
    print(week)

# 月の範囲を取得
weekday, days = calendar.monthrange(year, month)
print(f"\n{year}年{month}月:")
print(f"1日の曜日: {weekday} (0=月曜)")
print(f"日数: {days}日")

テキスト形式のカレンダー

TextCalendarクラスの使用

import calendar

# TextCalendarオブジェクトを作成
cal = calendar.TextCalendar()

# 月のカレンダーを文字列として取得
month_str = cal.formatmonth(2024, 1)
print("TextCalendarによる月表示:")
print(month_str)

# 年のカレンダーを文字列として取得
year_str = cal.formatyear(2024)
print("年間カレンダー(一部):")
print(year_str[:500] + "...")

カスタムフォーマットでのテキストカレンダー

import calendar

class CustomTextCalendar(calendar.TextCalendar):
    def formatday(self, day, weekday, width):
        """日付のフォーマットをカスタマイズ"""
        if day == 0:
            s = ''
        else:
            s = f'{day:2d}'
            
        # 土曜日を青色、日曜日を赤色で表示(色は表示されませんが、記号で区別)
        if weekday == 5:  # 土曜日
            s = f'[{s}]'
        elif weekday == 6:  # 日曜日
            s = f'({s})'
            
        return s.rjust(width)

# カスタムカレンダーの使用
custom_cal = CustomTextCalendar()
print("カスタムテキストカレンダー:")
print(custom_cal.formatmonth(2024, 1))

週の開始曜日を変更

import calendar

# 月曜日始まり(デフォルト)
cal_mon = calendar.TextCalendar(firstweekday=calendar.MONDAY)
print("月曜日始まり:")
print(cal_mon.formatmonth(2024, 1))

# 日曜日始まり
cal_sun = calendar.TextCalendar(firstweekday=calendar.SUNDAY)
print("\n日曜日始まり:")
print(cal_sun.formatmonth(2024, 1))

HTML形式のカレンダー

HTMLCalendarクラスの基本使用

import calendar

# HTMLCalendarオブジェクトを作成
html_cal = calendar.HTMLCalendar()

# 月のカレンダーをHTML形式で取得
html_month = html_cal.formatmonth(2024, 1)
print("HTMLカレンダー:")
print(html_month)

カスタムHTMLカレンダー

import calendar

class CustomHTMLCalendar(calendar.HTMLCalendar):
    def formatday(self, day, weekday):
        """日付のHTMLフォーマットをカスタマイズ"""
        if day == 0:
            return '<td class="noday">&nbsp;</td>'
        
        # 土日に特別なクラスを追加
        css_classes = []
        if weekday == 5:  # 土曜日
            css_classes.append('saturday')
        elif weekday == 6:  # 日曜日
            css_classes.append('sunday')
        
        # 今日の日付をハイライト
        from datetime import date
        today = date.today()
        if day == today.day and today.year == 2024 and today.month == 1:
            css_classes.append('today')
        
        class_attr = f' class="{" ".join(css_classes)}"' if css_classes else ''
        return f'<td{class_attr}>{day}</td>'

    def formatmonth(self, theyear, themonth, withyear=True):
        """月のHTMLフォーマットをカスタマイズ"""
        cal = super().formatmonth(theyear, themonth, withyear)
        
        # CSSスタイルを追加
        style = """
        <style>
        .calendar {
            border-collapse: collapse;
            margin: 20px auto;
        }
        .calendar td, .calendar th {
            border: 1px solid #ddd;
            padding: 8px;
            text-align: center;
        }
        .saturday { background-color: #e6f3ff; }
        .sunday { background-color: #ffe6e6; }
        .today { background-color: #ffff99; font-weight: bold; }
        .noday { background-color: #f5f5f5; }
        </style>
        """
        
        # テーブルにクラスを追加
        cal = cal.replace('<table', '<table class="calendar"')
        return style + cal

# カスタムHTMLカレンダーの使用
custom_html_cal = CustomHTMLCalendar()
html_with_style = custom_html_cal.formatmonth(2024, 1)
print("スタイル付きHTMLカレンダー:")
print(html_with_style)

HTMLファイルとして保存

import calendar
from datetime import date

def generate_html_calendar_file(year, month, filename=None):
    """HTMLカレンダーをファイルとして保存"""
    if filename is None:
        filename = f"calendar_{year}_{month:02d}.html"
    
    html_cal = calendar.HTMLCalendar()
    
    # HTMLテンプレート
    html_template = f"""
    <!DOCTYPE html>
    <html lang="ja">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>{year}年{month}月カレンダー</title>
        <style>
            body {{
                font-family: Arial, sans-serif;
                margin: 20px;
                background-color: #f0f0f0;
            }}
            .calendar {{
                border-collapse: collapse;
                margin: 20px auto;
                background-color: white;
                box-shadow: 0 2px 10px rgba(0,0,0,0.1);
            }}
            .calendar th, .calendar td {{
                border: 1px solid #ddd;
                padding: 10px;
                text-align: center;
                width: 40px;
                height: 40px;
            }}
            .calendar th {{
                background-color: #4CAF50;
                color: white;
                font-weight: bold;
            }}
            .calendar .sat {{
                background-color: #e3f2fd;
            }}
            .calendar .sun {{
                background-color: #ffebee;
            }}
            h1 {{
                text-align: center;
                color: #333;
            }}
        </style>
    </head>
    <body>
        <h1>{year}年{month}月</h1>
        {html_cal.formatmonth(year, month)}
    </body>
    </html>
    """
    
    with open(filename, 'w', encoding='utf-8') as f:
        f.write(html_template)
    
    print(f"HTMLカレンダーを'{filename}'に保存しました")

# HTMLファイルの生成
generate_html_calendar_file(2024, 1)

実用的な応用例

イベント付きカレンダー

import calendar
from datetime import date

class EventCalendar(calendar.HTMLCalendar):
    def __init__(self, events=None):
        super().__init__()
        self.events = events or {}
    
    def formatday(self, day, weekday):
        """イベント情報付きの日付フォーマット"""
        if day == 0:
            return '<td class="noday">&nbsp;</td>'
        
        # イベントがあるかチェック
        event_text = self.events.get(day, '')
        event_class = ' event' if event_text else ''
        
        # 土日のクラス
        weekend_class = ''
        if weekday == 5:
            weekend_class = ' saturday'
        elif weekday == 6:
            weekend_class = ' sunday'
        
        return f'<td class="day{weekend_class}{event_class}" title="{event_text}">{day}</td>'

# イベントデータの例
events = {
    1: "新年",
    15: "会議",
    25: "プレゼンテーション"
}

# イベント付きカレンダーの生成
event_cal = EventCalendar(events)
html_calendar = event_cal.formatmonth(2024, 1)

# スタイル付きHTMLとして出力
full_html = f"""
<style>
.calendar {{ border-collapse: collapse; margin: 20px auto; }}
.calendar td, .calendar th {{ border: 1px solid #ddd; padding: 8px; text-align: center; }}
.saturday {{ background-color: #e6f3ff; }}
.sunday {{ background-color: #ffe6e6; }}
.event {{ background-color: #fff2cc; font-weight: bold; }}
</style>
{html_calendar}
"""
print("イベント付きカレンダー:")
print(full_html)

複数月表示カレンダー

import calendar

def generate_multi_month_calendar(year, start_month, num_months):
    """複数月のカレンダーを生成"""
    cal = calendar.TextCalendar()
    
    print(f"=== {year}年 {start_month}月〜{start_month + num_months - 1}月 ===\n")
    
    for i in range(num_months):
        month = start_month + i
        if month > 12:
            month = month - 12
            year += 1
        
        print(f"{year}年{month}月")
        print("=" * 20)
        print(cal.formatmonth(year, month))
        print()

# 3ヶ月分のカレンダーを表示
generate_multi_month_calendar(2024, 1, 3)

祝日対応カレンダー

import calendar

class JapaneseHolidayCalendar(calendar.TextCalendar):
    def __init__(self):
        super().__init__()
        # 簡略化した祝日データ
        self.holidays = {
            (1, 1): "元日",
            (2, 11): "建国記念の日",
            (4, 29): "昭和の日",
            (5, 3): "憲法記念日",
            (5, 4): "みどりの日",
            (5, 5): "こどもの日",
        }
    
    def formatday(self, day, weekday, width):
        """祝日を考慮した日付フォーマット"""
        if day == 0:
            return ''.rjust(width)
        
        # 祝日チェック
        holiday = self.holidays.get((1, day))  # 1月の例
        if holiday:
            return f'{day:2d}*'.rjust(width)  # 祝日に*を付ける
        elif weekday == 6:  # 日曜日
            return f'{day:2d}』'.rjust(width)
        elif weekday == 5:  # 土曜日
            return f'{day:2d}』'.rjust(width)
        else:
            return f'{day:2d}'.rjust(width)

# 祝日対応カレンダーの表示
holiday_cal = JapaneseHolidayCalendar()
print("祝日対応カレンダー(*=祝日):")
print(holiday_cal.formatmonth(2024, 1))

カレンダー情報の抽出

import calendar
from datetime import date, timedelta

def calendar_statistics(year, month):
    """カレンダーの統計情報を取得"""
    # 月の基本情報
    weekday_start, days_in_month = calendar.monthrange(year, month)
    
    # 曜日ごとの日数をカウント
    weekday_counts = [0] * 7
    
    for day in range(1, days_in_month + 1):
        dt = date(year, month, day)
        weekday_counts[dt.weekday()] += 1
    
    weekday_names = ['月', '火', '水', '木', '金', '土', '日']
    
    print(f"=== {year}年{month}月の統計 ===")
    print(f"総日数: {days_in_month}日")
    print(f"1日の曜日: {weekday_names[weekday_start]}曜日")
    print("\n曜日別日数:")
    for i, count in enumerate(weekday_counts):
        print(f"  {weekday_names[i]}曜日: {count}日")
    
    # 週末の日数
    weekend_days = weekday_counts[5] + weekday_counts[6]
    business_days = days_in_month - weekend_days
    print(f"\n営業日: {business_days}日")
    print(f"週末: {weekend_days}日")
    
    return {
        'total_days': days_in_month,
        'weekday_counts': weekday_counts,
        'business_days': business_days,
        'weekend_days': weekend_days
    }

# 統計情報の表示
stats = calendar_statistics(2024, 1)

カレンダーデータのエクスポート

import calendar
import json
from datetime import date

def export_calendar_data(year, month, format='json'):
    """カレンダーデータを指定形式でエクスポート"""
    month_calendar = calendar.monthcalendar(year, month)
    
    calendar_data = {
        'year': year,
        'month': month,
        'month_name': calendar.month_name[month],
        'weeks': []
    }
    
    weekday_names = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 
                    'Friday', 'Saturday', 'Sunday']
    
    for week in month_calendar:
        week_data = []
        for i, day in enumerate(week):
            if day == 0:
                week_data.append(None)
            else:
                day_info = {
                    'day': day,
                    'weekday': weekday_names[i],
                    'is_weekend': i >= 5
                }
                week_data.append(day_info)
        calendar_data['weeks'].append(week_data)
    
    if format == 'json':
        filename = f'calendar_{year}_{month:02d}.json'
        with open(filename, 'w', encoding='utf-8') as f:
            json.dump(calendar_data, f, ensure_ascii=False, indent=2)
        print(f"JSONデータを'{filename}'に保存しました")
    
    return calendar_data

# カレンダーデータのエクスポート
calendar_data = export_calendar_data(2024, 1)
print("エクスポートされたデータの一部:")
print(json.dumps(calendar_data['weeks'][0], ensure_ascii=False, indent=2))

まとめ

  • 基本機能calendar.month(), calendar.calendar(), monthcalendar()
  • テキスト出力TextCalendarクラスでカスタマイズ可能
  • HTML出力HTMLCalendarクラスでWebページ生成
  • 実用例:イベント付きカレンダー、祝日対応、統計情報
  • データ形式:JSON、HTML、テキストでのエクスポート

calendarモジュールを活用することで、様々な形式のカレンダー表示・出力が効率的に実現できます。

■「らくらくPython塾」が切り開く「呪文コーディング」とは?

■プロンプトだけでオリジナルアプリを開発・公開してみた!!

■AI時代の第一歩!「AI駆動開発コース」はじめました!

テックジム東京本校で先行開始。

■テックジム東京本校

「武田塾」のプログラミング版といえば「テックジム」。
講義動画なし、教科書なし。「進捗管理とコーチング」で効率学習。
より早く、より安く、しかも対面型のプログラミングスクールです。

<短期講習>5日で5万円の「Pythonミニキャンプ」開催中。

<月1開催>放送作家による映像ディレクター養成講座

<オンライン無料>ゼロから始めるPython爆速講座