跳转至

公历转换为农历

详情参见 GitHub

'''
公历农历转换

作者:HuangFuSL

依赖包:pythonnet

输入格式:
2022 - 输出2022年的所有农历日期
202202 - 输出2022年2月的所有农历日期
20220202 - 输出2022年2月2日的农历日期
其他 - 输出当天的农历日期

输出格式
2022-12-28 十一月初六
'''

import datetime
import itertools
import sys
from typing import Any, List

try:
    import clr

    clr.AddReference("System.Globalization")
    from System import DateTime  # type: ignore
    from System.Globalization import ChineseLunisolarCalendar  # type: ignore
except ImportError:
    sys.exit(-1)


class InvalidInput(Exception):

    def __init__(self, *args) -> None:
        super().__init__(*args)

    def __str__(self) -> str:
        return 'Invalid Input'


CALENDAR = ChineseLunisolarCalendar()
NUMBER_LOOKUP = [
    '初', '一', '二', '三', '四', '五', '六', '七', '八', '九', '十', '十一', '十二'
]
TEN_LOOKUP = '初十廿三'


def build_result(cn_month: int, cn_day: int) -> str:
    ''' 数字转文本 '''
    if cn_day % 10:
        day = TEN_LOOKUP[cn_day // 10] + NUMBER_LOOKUP[cn_day % 10]
    else:
        day = TEN_LOOKUP[cn_day // 10] + '十'
        if day[0] == '十':
            day = NUMBER_LOOKUP[0] + '十'

    if cn_month != 1:
        month = NUMBER_LOOKUP[cn_month] + '月'
    else:
        month = '正月'

    return month + day


def convert(date: DateTime) -> str:
    ''' 调用C#函数库 '''
    cn_year = CALENDAR.GetYear(date)
    cn_month = CALENDAR.GetMonth(date)
    cn_day = CALENDAR.GetDayOfMonth(date)
    leap_month = CALENDAR.GetLeapMonth(cn_year)
    true_month = cn_month if cn_month < leap_month else cn_month - 1
    return ('闰' if cn_month == leap_month else '') + build_result(true_month, cn_day)


def get_day_iter(y: int, m: int):
    ''' 获取月份天数 '''
    lookup = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
    days_total = lookup[m] + 1
    if m == 2 and (y % 4 == 0 and y % 100 != 0 or y % 400 == 0):
        days_total += 1
    yield from range(1, days_total)


if __name__ == "__main__":
    def to_list(_): return [int(_)]
    date_str = input().strip()

    try:
        if len(date_str) == 8:
            y, m, d = map(to_list, [date_str[:4], date_str[4:6], date_str[6:]])
        elif len(date_str) == 6:
            y, m = map(to_list, [date_str[:4], date_str[4:]])
            d = None
        elif len(date_str) == 4:
            y = to_list(date_str[:4])
            m, d = range(1, 13), None
        else:
            raise InvalidInput()
    except InvalidInput:
        y, m, d = map(to_list, [datetime.date.today().timetuple()[:3]])

    for a, b in itertools.product(y, m):
        for c in d if d is not None else get_day_iter(a, b):
            print(f'{datetime.date(a, b, c):%Y-%m-%d} {convert(DateTime(a, b, c))}')

评论