#! /usr/bin/env python """ Description: Programm zur Ausgabe einer Ansicht eines Monats wie gängige Kalender-Format Usage: ``` $ python month_of_year.py 12 2024 ``` """ from typing import Final import sys # Calender setup weekdays: Final[tuple[str, ...]] = ("So", "Mo", "Di", "Mi", "Do", "Fr", "Sa") first_day_of_week: Final[int] = 1 # it is monday, common in Europa months: Final[tuple[ tuple[str, int], ...]] = (("", 0), ("Januar", 31), ("Februar", 28), ("März", 31), ("April", 30), ("Mai", 31), ("Juni", 30), ("July", 31), ("August", 31), ("September", 30), ("Oktober", 31), ("November", 30), ("Dezember", 31)) def is_leap_year(year: int) -> bool: return (year % 4 == 0 and year % 100 != 0) or (year % 400 == 0) def weekday_of_date(day: int, month: int, year: int) -> int: y0 = year - ((14 - month) // 12) x = y0 + (y0 // 4) - (y0 // 100) + (y0 // 400) m0 = month + 12 * ((14 - month) // 12) - 2 return (day + x +(31 * m0) // 12) % 7 def count_days_in_month(month: int, year: int) -> int: count_days = months[month][1] if month == 2 and is_leap_year(year): count_days += 1 return count_days def build_calendar_head(month: int, year: int, calendar_width: int, fill_char: str =' ') -> str: head_line = f"{months[month][0]} {year}" return head_line.center(calendar_width, fill_char) def build_weekdays_line(column_width) -> str: wd_line = "" for i in range(0, 7): d = (i + first_day_of_week) % 7 wd_line += f"{weekdays[d]}".rjust(column_width, ' ') return wd_line def format_day(day: int, column_width: int) -> str: return f"{day}".rjust(column_width) def build_month_view(month: int, year: int, column_width: int) -> str: month_view = "" day = 1 # the first week day_of_first_date = weekday_of_date(day, month, year) # how many columns before the first day of this month diff = (7 + day_of_first_date - first_day_of_week) % 7 # -> empty column for _ in range(diff, 0, -1): month_view += ("#"*(column_width - 1) + "-") # -> next days in the first week while day + diff <= 7: month_view += format_day(day, column_width) day += 1 month_view += "\n" # next weeks days_in_month = count_days_in_month(month, year) while day <= days_in_month: month_view += format_day(day, column_width) if (day + diff) % 7 == 0: month_view += "\n" day += 1 return month_view def build_calendar(month: int, year: int, column_width: int = 3) -> str: calendar_width = 7 * column_width head_line = build_calendar_head(month, year, calendar_width, fill_char="-") calendar_view = f"{head_line}\n" weekdays_line = build_weekdays_line(column_width) calendar_view += f"{weekdays_line}\n" month_view = build_month_view(month, year, column_width) calendar_view += f"{month_view}\n" return calendar_view if __name__ == "__main__": month = int(sys.argv[1]) year = int(sys.argv[2]) cal = build_calendar(month, year, 4) print(cal)