万年历

点击查看代码
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import sys
import argparse
from datetime import datetime

# ---------- 日期计算函数 ----------
def is_leap(year):
    """判断是否为闰年"""
    return (year % 4 == 0 and year % 100 != 0) or (year % 400 == 0)

def days_in_month(year, month):
    """返回指定年月的天数"""
    if month in (4, 6, 9, 11):
        return 30
    elif month == 2:
        return 29 if is_leap(year) else 28
    else:
        return 31

def days_since_2000(year, month, day):
    """计算从 2000-01-01 到指定日期的天数(不含指定日期当天)"""
    days = 0
    for y in range(2000, year):
        days += 366 if is_leap(y) else 365
    for m in range(1, month):
        days += days_in_month(year, m)
    days += day - 1
    return days

def first_day_of_month(year, month):
    """
    返回指定月份第一天是星期几
    返回值:0=星期日, 1=星期一, ..., 6=星期六
    基准:2000-01-01 是星期六(值为6)
    """
    diff = days_since_2000(year, month, 1)
    return (6 + diff) % 7

# ---------- 打印函数 ----------
def print_month(year, month, title=True):
    """打印单个月份的日历"""
    month_names = ['', '一月', '二月', '三月', '四月', '五月', '六月',
                   '七月', '八月', '九月', '十月', '十一月', '十二月']
    if title:
        print(f"{month_names[month]} {year}".center(20))
        print("日 一 二 三 四 五 六")

    first_wd = first_day_of_month(year, month)
    days = days_in_month(year, month)

    # 打印第一行空格
    print("   " * first_wd, end="")
    for d in range(1, days + 1):
        print(f"{d:2d}", end=" ")
        if (first_wd + d) % 7 == 0:
            print()
    if (first_wd + days) % 7 != 0:
        print()

def print_year(year):
    """打印整年的日历,每行显示三个月"""
    month_names = ['', '一月', '二月', '三月', '四月', '五月', '六月',
                   '七月', '八月', '九月', '十月', '十一月', '十二月']

    # 每三个月份为一组
    for m in range(1, 13, 3):
        # 构造标题行
        titles = []
        for i in range(3):
            mon = m + i
            if mon > 12:
                break
            titles.append(f"{month_names[mon]} {year}".center(20))
        print("   ".join(titles))

        # 星期行
        weeks = ["日 一 二 三 四 五 六"] * len(titles)
        print("   ".join(weeks))

        # 准备每个月份的行数据
        month_lines = []
        for i in range(len(titles)):
            mon = m + i
            first_wd = first_day_of_month(year, mon)
            days = days_in_month(year, mon)

            lines = []
            # 第一行(可能含前导空格)
            line = []
            for j in range(7):
                if j < first_wd:
                    line.append("  ")
                else:
                    d = j - first_wd + 1
                    if d <= days:
                        line.append(f"{d:2d}")
                    else:
                        line.append("  ")
            lines.append(" ".join(line))

            # 后续行
            d = 7 - first_wd + 1
            while d <= days:
                line = []
                for j in range(7):
                    if d <= days:
                        line.append(f"{d:2d}")
                        d += 1
                    else:
                        line.append("  ")
                lines.append(" ".join(line))
            month_lines.append(lines)

        # 按行输出三个月份的日历
        max_rows = max(len(lines) for lines in month_lines)
        for row_idx in range(max_rows):
            row_parts = []
            for lines in month_lines:
                if row_idx < len(lines):
                    row_parts.append(lines[row_idx])
                else:
                    # 用空白填充(长度等于第一行)
                    row_parts.append(" " * len(month_lines[0][0]))
            print("   ".join(row_parts))
        print()  # 每组之间空一行

# ---------- 命令行入口 ----------
def main():
    parser = argparse.ArgumentParser(description="万年历 - 显示公历月份或整年日历")
    parser.add_argument("year", nargs="?", type=int, help="年份 (例如 2026)")
    parser.add_argument("month", nargs="?", type=int, help="月份 (1-12),若仅指定年份则显示全年")
    args = parser.parse_args()

    now = datetime.now()
    if args.year is None:
        # 无参数:显示当前月份
        print_month(now.year, now.month)
    elif args.month is None:
        # 只有年份:显示全年
        print_year(args.year)
    else:
        # 年份 + 月份
        print_month(args.year, args.month)

if __name__ == "__main__":
    main()
posted @ 2026-07-31 09:47  Junhuit  阅读(5)  评论(0)    收藏  举报