Files
lunar-converter/chrono_converter.py
Timmy ae21a0ae66 Initial commit: Lunar calendar converter project
- Add lunar calendar astronomical calculation engine (lunar_calendar.py)
- Add converter utilities for solar/lunar date conversion
- Add historical era name conversions (chrono_converter.py, converter_with_eras.py)
- Add FastAPI REST API for date conversion services
- Add age calculator using lunar calendar
- Add batch generation script for lunar calendar JSON data
- Add project documentation (CLAUDE.md, pyproject.toml)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-09 13:51:45 +08:00

214 lines
6.7 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
from datetime import date
class ChronoConverter:
# 太平天國
TP_START = (1851, 2, 1)
TP_END = (1872, 7, 5)
# 清朝年號區間(含康熙到宣統)
KX_START = date(1662, 2, 18)
KX_END = date(1723, 2, 4)
YZ_START = date(1723, 2, 5)
YZ_END = date(1736, 2, 11)
QL_START = date(1736, 2, 12)
QL_END = date(1796, 2, 8)
JQ_START = date(1796, 2, 9)
JQ_END = date(1821, 2, 2)
DG_START = date(1821, 2, 3)
DG_END = date(1851, 1, 31)
XF_START = date(1851, 2, 1)
XF_END = date(1862, 1, 29)
TZ_START = date(1862, 1, 30)
TZ_END = date(1875, 2, 5)
GX_START = date(1875, 2, 6)
GX_END = date(1909, 1, 21)
XT_START = date(1909, 1, 22)
XT_END = date(1912, 2, 17)
# 清太祖天命 & 順治
TN_START = date(1616, 2, 17)
TN_END = date(1627, 2, 15)
SZ_START = date(1644, 2, 8)
SZ_END = date(1662, 2, 17)
# 明朝年號
WL_START = date(1573, 1, 30)
WL_END = date(1620, 8, 18)
TQ_START = date(1620, 8, 19)
TQ_END = date(1627, 9, 29)
CZ_START = date(1628, 2, 5)
CZ_END = date(1644, 4, 25)
@staticmethod
def to_minguo(year: int) -> str:
if year < 1912:
return f"西元 {year} 年,尚未進入民國"
return f"民國 {year - 1911}"
@staticmethod
def to_ad_from_minguo(minguo_year: int) -> str:
if minguo_year <= 0:
return "民國元年從西元 1912 年開始,不能為 0 或負數"
return f"西元 {minguo_year + 1911}"
@classmethod
def to_taiping(cls, year: int, month: int = 1, day: int = 1) -> str:
if (year, month, day) < cls.TP_START:
return f"西元 {year}{month}{day} 日尚未進入太平天國年間"
elif (year, month, day) > cls.TP_END:
return f"西元 {year}{month}{day} 日已超過太平天國年間"
else:
tp_year = year - 1850
return f"太平天國 {tp_year}"
@staticmethod
def to_ad_from_taiping(tp_year: int) -> str:
if 1 <= tp_year <= 22:
return f"西元 {tp_year + 1850} 年(約太平天國 {tp_year} 年)"
else:
return f"太平天國 {tp_year} 年超出有效範圍122"
@classmethod
def to_tianming(cls, y: int, m: int = 1, d: int = 1) -> str:
try:
input_date = date(y, m, d)
except ValueError:
return "無效的日期"
if input_date < cls.TN_START:
return f"西元 {y}{m}{d} 日尚未進入天命年間"
elif input_date > cls.TN_END:
return f"西元 {y}{m}{d} 日已超過天命年間"
else:
return f"清太祖天命 {y - 1615}"
@staticmethod
def to_ad_from_tianming(tn_year: int) -> str:
if 1 <= tn_year <= 12:
return f"西元 {tn_year + 1615} 年(約天命 {tn_year} 年)"
else:
return "天命年間僅有 112 年"
@classmethod
def to_shunzhi(cls, y: int, m: int = 1, d: int = 1) -> str:
try:
input_date = date(y, m, d)
except ValueError:
return "無效的日期"
if input_date < cls.SZ_START:
return f"西元 {y}{m}{d} 日尚未進入順治年間"
elif input_date > cls.SZ_END:
return f"西元 {y}{m}{d} 日已超過順治年間"
else:
return f"清世祖順治 {y - 1643}"
@staticmethod
def to_ad_from_shunzhi(sz_year: int) -> str:
if 1 <= sz_year <= 18:
return f"西元 {sz_year + 1643} 年(約順治 {sz_year} 年)"
else:
return "順治年間僅有 118 年"
@classmethod
def to_qing_dynasty(cls, y: int, m: int = 1, d: int = 1) -> str:
try:
input_date = date(y, m, d)
except ValueError:
return "無效的日期"
ranges = [
(cls.KX_START, cls.KX_END, 1661, "清聖祖康熙", 1),
(cls.YZ_START, cls.YZ_END, 1722, "清世宗雍正", 1),
(cls.QL_START, cls.QL_END, 1735, "清高宗乾隆", 1),
(cls.JQ_START, cls.JQ_END, 1795, "清仁宗嘉慶", 1),
(cls.DG_START, cls.DG_END, 1820, "清宣宗道光", 1),
(cls.XF_START, cls.XF_END, 1850, "清文宗咸豐", 1),
(cls.TZ_START, cls.TZ_END, 1861, "清穆宗同治", 1),
(cls.GX_START, cls.GX_END, 1874, "清德宗光緒", 1),
(cls.XT_START, cls.XT_END, 1908, "清遜帝宣統", 1),
]
for start, end, base_year, label, base_era in ranges:
if start <= input_date <= end:
return f"{label} {y - base_year + base_era}"
return f"西元 {y}{m}{d} 日不在清代指定年號範圍內"
@classmethod
def to_ming_dynasty(cls, y: int, m: int = 1, d: int = 1) -> str:
try:
input_date = date(y, m, d)
except ValueError:
return "無效的日期"
ranges = [
(cls.WL_START, cls.WL_END, 1572, "明神宗萬曆", 1),
(cls.TQ_START, cls.TQ_END, 1619, "明熹宗天啟", 1),
(cls.CZ_START, cls.CZ_END, 1627, "明思宗崇禎", 1),
]
for start, end, base_year, label, base_era in ranges:
if start <= input_date <= end:
return f"{label} {y - base_year + base_era}"
return f"西元 {y}{m}{d} 日不在明代指定年號範圍內"
@staticmethod
def weekday_str(y: int, m: int, d: int) -> str:
try:
dt = date(y, m, d)
return dt.strftime("%A")
except ValueError:
return "無效日期"
# 檢查當前程式是否被作為主程式執行
if __name__ == "__main__":
def convert_date(y: int, m: int, d: int) -> dict:
cc = ChronoConverter()
raw = {
"民國": cc.to_minguo(y),
"太平天國": cc.to_taiping(y, m, d),
"清太祖天命": cc.to_tianming(y, m, d),
"清世祖順治": cc.to_shunzhi(y, m, d),
"清朝其他年號": cc.to_qing_dynasty(y, m, d),
"明朝晚期年號": cc.to_ming_dynasty(y, m, d),
"星期": cc.weekday_str(y, m, d),
}
# 過濾掉無效的年號資訊
filtered = {
k: v for k, v in raw.items()
if not (
"尚未進入" in v or
"已超過" in v or
"不在" in v or
"無效" in v
)
}
return filtered
# result = convert_date(1851, 2, 1)
# result = convert_date(1977, 10, 12)
result = convert_date(1906, 2, 7)
# result = convert_date(1967, 10, 17)
print(result)
for key, val in result.items():
print(f"{key}{val}")