研究2:日本の祝日を反映した見やすいカレンダーの作成と可視化

Hayate.Labに戻る

 【実現したいこと(Must要件)】
  ①画面の左右どちらかの半分のみにカレンダーを描画すること
  ②各日付をセルごとで区分けし、その境界線を描画すること
  ③日曜・祝日は赤色、土曜日は水色、平日は黒色の文字とすること
  ④現在の日付はセル内を塗りつぶすことで表現すること
  ⑤祝日は一か月毎に、最新の情報となるようにすること。(専用ライブラリの使用)
  ⑥カレンダーは壁外の上に重ねて描画すること
  ⑦月名はカレンダー上部に記載すること
  ⑧カレンダーは全画面表示にすること
  ⑨本カレンダーは1日1回更新されるようにすること

この要件を満たすように、コードを記述すると下記のようになります。

from PIL import Image, ImageDraw, ImageFont
import datetime
import jpholiday
import calendar
import pygame
from datetime import datetime, timedelta
import time

def create_calendar_image(year, month, day):
    # 祝日を取得する関数
    def get_holidays(year, month):
        first_day = datetime(year, month, 1)
        last_day = (first_day + timedelta(days=32)).replace(day=1) - timedelta(days=1)
        holidays = []
        for day in range(1, last_day.day + 1):
            date = datetime(year, month, day)
            if jpholiday.is_holiday(date):
                holidays.append(day)
        return holidays

    # フォントの読み込み
    font_path = "/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf"  # DejaVu Sansのフォントファイルパス
    font_size_month = 40
    font_size_days = 20
    font_month = ImageFont.truetype(font_path, font_size_month)
    font_days = ImageFont.truetype(font_path, font_size_days)

    # 画像サイズ
    image_width = 800
    image_height = 480
    background_color = (255, 255, 255)
    image = Image.new("RGB", (image_width, image_height), background_color)
    draw = ImageDraw.Draw(image)

    # 月に応じた背景画像の選択
    background_images = ["1.png", "2.png", "3.png", "4.png", "5.png", "6.png"]
    bg_image_file = background_images[(month - 1) % len(background_images)]

    # 背景画像の描画
    bg_image = Image.open(bg_image_file)
    bg_image = bg_image.resize((image_width, image_height), Image.Resampling.LANCZOS)
    image.paste(bg_image, (0, 0))

    # カレンダーの設定
    cal = calendar.Calendar(firstweekday=6)  # 日曜日から始まる
    month_days = cal.monthdayscalendar(year, month)
    holidays = get_holidays(year, month)

    # セルのサイズ(正方形)
    if bg_image_file == "4.png":
        cell_size = min((image_width * 0.8 // 2 - 10) // 7, (image_height - 100) // len(month_days))  # 月名のために高さを減らす
    else:
        cell_size = min((image_width // 2 - 10) // 7, (image_height - 100) // len(month_days))  # 月名のために高さを減らす

    cell_width = cell_size
    cell_height = cell_size

    # カレンダーの位置設定
    if bg_image_file == "1.png":
        calendar_x_offset = image_width // 2 + 10
        calendar_y_offset = (image_height - (cell_height * len(month_days))) // 2 + 50  # 月名のためにオフセットを増やす
    elif bg_image_file in ["2.png", "3.png", "6.png"]:
        calendar_x_offset = 10
        calendar_y_offset = (image_height - (cell_height * len(month_days))) // 2 + 50  # 月名のためにオフセットを増やす
    elif bg_image_file == "4.png":
        calendar_x_offset = image_width - (cell_width * 7) - 10
        calendar_y_offset = 80  # 月名のためにオフセットを増やす
    elif bg_image_file == "5.png":
        calendar_x_offset = 10
        calendar_y_offset = 80  # 月名のためにオフセットを増やす

    # 月名の描画
    month_name = now.strftime("%B")
    month_name_pos = (calendar_x_offset, calendar_y_offset - 50)  # カレンダーの上に配置
    draw.text(month_name_pos, month_name, font=font_month, fill="black")

    # カレンダーの日付の描画
    for week_index, week in enumerate(month_days):
        for day_index, day in enumerate(week):
            if day != 0:  # 0はその月に含まれない日付
                day_str = str(day)
                x = calendar_x_offset + day_index * cell_width + cell_width // 2
                y = calendar_y_offset + week_index * cell_height + cell_height // 2
                # 今日の日付のセルを薄緑で塗りつぶす
                if now.day == day:
                    draw.rectangle(
                        [x - cell_width // 2, y - cell_height // 2, x + cell_width // 2, y + cell_height // 2],
                        fill="lightgreen"
                    )
                # 祝日の色を赤色に設定
                if day in holidays:
                    fill_color = "red"
                elif day_index == 0:  # 日曜日
                    fill_color = "red"
                elif day_index == 6:  # 土曜日
                    fill_color = "blue"
                else:
                    fill_color = "black"
                # 日付の描画
                draw.text((x, y), day_str, font=font_days, fill=fill_color, anchor="mm")
                # グリッド線の描画
                draw.rectangle(
                    [x - cell_width // 2, y - cell_height // 2, x + cell_width // 2, y + cell_height // 2],
                    outline="black"
                )

    # 画像の保存
    image.save("calendar.png")

# Pygameを使って画像を全画面表示
pygame.init()
screen = pygame.display.set_mode((800, 480), pygame.FULLSCREEN)

# メインループ
running = True
while running:
    now = datetime.now()
    create_calendar_image(now.year, now.month, now.day)
    calendar_image = pygame.image.load("calendar.png")
    
    for event in pygame.event.get():
        if event.type == pygame.QUIT or (event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE):
            running = False

    screen.blit(calendar_image, (0, 0))
    pygame.display.flip()

    time.sleep(60)  # 86400秒(1日)待機

pygame.quit()

Hayate.Labに戻る

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA