#!/usr/bin/env python3 # coding=utf-8 # Thomas Chung # 2025-01-08 import datetime ############################################################################### # 1. Hard-coded Lunar Month Data for 2025 (KST) ############################################################################### LUNAR_MONTHS_2025 = [ (datetime.date(2024, 12, 30), datetime.date(2025, 1, 28), 2024, 12, False), (datetime.date(2025, 1, 29), datetime.date(2025, 2, 27), 2025, 1, False), (datetime.date(2025, 2, 28), datetime.date(2025, 3, 28), 2025, 2, False), (datetime.date(2025, 3, 29), datetime.date(2025, 4, 27), 2025, 3, False), (datetime.date(2025, 4, 28), datetime.date(2025, 5, 27), 2025, 4, False), (datetime.date(2025, 5, 28), datetime.date(2025, 6, 25), 2025, 5, False), (datetime.date(2025, 6, 26), datetime.date(2025, 7, 24), 2025, 5, True), (datetime.date(2025, 7, 25), datetime.date(2025, 8, 22), 2025, 6, False), (datetime.date(2025, 8, 23), datetime.date(2025, 9, 21), 2025, 7, False), (datetime.date(2025, 9, 22), datetime.date(2025, 10, 21), 2025, 8, False), (datetime.date(2025, 10, 22), datetime.date(2025, 11, 19), 2025, 9, False), (datetime.date(2025, 11, 20), datetime.date(2025, 12, 19), 2025, 10, False), (datetime.date(2025, 12, 20), datetime.date(2026, 1, 17), 2025, 11, False), (datetime.date(2026, 1, 18), datetime.date(2026, 2, 15), 2025, 12, False), ] ############################################################################### # 2. Important Dates (in Korean) for 2025 ############################################################################### IMPORTANT_DATES_2025 = { # Solar-based datetime.date(2025, 1, 1): "신정", datetime.date(2025, 1, 27): "임시공휴일", # <-- 임시공휴일 지정 datetime.date(2025, 1, 28): "설날 전날", datetime.date(2025, 1, 29): "설날", datetime.date(2025, 1, 30): "설날 다음 날", datetime.date(2025, 3, 1): "삼일절", datetime.date(2025, 3, 3): "대체공휴일", # <-- ADDED datetime.date(2025, 5, 5): "어린이날, 부처님 오신 날", datetime.date(2025, 5, 6): "대체공휴일", # <-- ADDED datetime.date(2025, 6, 6): "현충일", datetime.date(2025, 7, 17): "제헌절", datetime.date(2025, 8, 15): "광복절", datetime.date(2025, 10, 3): "개천절", datetime.date(2025, 10, 5): "추석 전날", datetime.date(2025, 10, 6): "추석", datetime.date(2025, 10, 7): "추석 다음 날", datetime.date(2025, 10, 8): "대체공휴일", # <-- ADDED datetime.date(2025, 10, 9): "한글날", datetime.date(2025, 12, 25): "성탄절", } ############################################################################### # 3. Functions to Build and Render the Calendar ############################################################################### def get_korean_lunar_date(gregorian_date): """ Returns (lunar_year, lunar_month, lunar_day, is_leap) if within 2025 data, else None. """ for (start_date, end_date, lunar_year, lunar_month, is_leap) in LUNAR_MONTHS_2025: if start_date <= gregorian_date <= end_date: day_in_lunar_month = (gregorian_date - start_date).days + 1 return (lunar_year, lunar_month, day_in_lunar_month, is_leap) return None def build_month_calendar_matrix(year, month): """ Returns a list-of-lists (6 rows x 7 cols) for a Sunday-start layout. Each cell = (date_obj, lunar_info) or None. """ first_day = datetime.date(year, month, 1) # Python weekday(): Monday=0, Sunday=6 => offset = (weekday+1) % 7 offset = (first_day.weekday() + 1) % 7 if month == 12: next_month = datetime.date(year + 1, 1, 1) else: next_month = datetime.date(year, month + 1, 1) last_day = next_month - datetime.timedelta(days=1) rows = [[None]*7 for _ in range(6)] current_day = 1 row = 0 col = offset while current_day <= last_day.day: current_date = datetime.date(year, month, current_day) lunar_info = get_korean_lunar_date(current_date) rows[row][col] = (current_date, lunar_info) current_day += 1 col += 1 if col > 6: col = 0 row += 1 if row > 5: break return rows def generate_month_table_html(year, month): """ Generates an HTML snippet for one month's calendar table, including lunar dates and holiday highlights for 2025. """ day_of_week_labels = ["일", "월", "화", "수", "목", "금", "토"] calendar_matrix = build_month_calendar_matrix(year, month) month_kor = f"{month}월" lines = [] # Centered heading lines.append( f"

" f"{year}년 {month_kor}

" ) lines.append("") lines.append(" ") for label in day_of_week_labels: lines.append(f" ") lines.append(" ") lines.append(" ") for row in calendar_matrix: lines.append(" ") for cell in row: if cell is None: lines.append("") else: (date_obj, lunar_info) = cell solar_day = date_obj.day # Check if there's a holiday holiday_name = IMPORTANT_DATES_2025.get(date_obj, None) # Check lunar info if lunar_info is not None: (lyear, lmonth, lday, is_leap) = lunar_info lunar_str = f"윤{lmonth}/{lday}" if is_leap else f"{lmonth}/{lday}" else: lunar_str = "N/A" # Base text: Solar day + (Lunar day) cell_html = f"{solar_day}
({lunar_str})" # If there's a holiday, display it in red if holiday_name: cell_html += f"
{holiday_name}" lines.append(f"") lines.append(" ") lines.append(" ") lines.append("
{label}
{cell_html}
") return "\n".join(lines) def lunar_2025(): """ Builds one big HTML document for Jan~Dec 2025, with lunar data & holidays. """ html_parts = [] html_parts.append("") html_parts.append("") html_parts.append("") html_parts.append(" ") html_parts.append(" 2025년 한국달력") # Basic CSS html_parts.append(" ") html_parts.append("") html_parts.append("") html_parts.append("

2025년 한국달력 (음력 포함)

") # Generate each month for m in range(1, 13): month_html = generate_month_table_html(2025, m) html_parts.append(f"
{month_html}
") html_parts.append("") html_parts.append("") return "\n".join(html_parts) def main(): html_content = lunar_2025() filename = "lunar_2025.html" with open(filename, "w", encoding="utf-8") as f: f.write(html_content) print(f"달력이 '{filename}' 파일로 생성되었습니다.") if __name__ == "__main__": main()