
代码逻辑
- 使用
print("首周数据示例:")
输出标题 - 遍历
data["weeks"][0]
中的每一天数据 - 如果当天数据存在,则分别打印阳历和农历日期
输出格式
- 阳历格式:
阳历 {day['solar_day']} 号
- 农历格式:
农历 {day['lunar_day']} 号
示例输出
import datetime
import lunardate
print(f"lunardate version: {lunardate.__version__ if hasattr(lunardate, '__version__') else 'unknown'}")
print(f"lunardate dir: {dir(lunardate.LunarDate)}")
class LunarSolarCalendar:
"""阳历农历双历日历生成器"""
LUNAR_MONTHS = {
1: '正月', 2: '二月', 3: '三月', 4: '四月',
5: '五月', 6: '六月', 7: '七月', 8: '八月',
9: '九月', 10: '十月', 11: '冬月', 12: '腊月'
}
LUNAR_DAYS = {
1: '初一', 2: '初二', 3: '初三', 4: '初四', 5: '初五',
6: '初六', 7: '初七', 8: '初八', 9: '初九', 10: '初十',
11: '十一', 12: '十二', 13: '十三', 14: '十四', 15: '十五',
16: '十六', 17: '十七', 18: '十八', 19: '十九', 20: '二十',
21: '廿一', 22: '廿二', 23: '廿三', 24: '廿四', 25: '廿五',
26: '廿六', 27: '廿七', 28: '廿八', 29: '廿九', 30: '三十'
}
def __init__(self, year: int, month: int, day: int = None):
"""
初始化日历对象
:param year: 年份(大于0的整数)
:param month: 月份(1-12的整数)
:param day: 日期(1-31的整数,可选)
"""
self._validate_input(year, month, day)
self.year = year
self.month = month
self.day = day
self._solar_days = self._get_month_days()
self._first_weekday = self._get_first_weekday()
@staticmethod
def _validate_input(year, month, day=None):
"""验证输入有效性"""
if not isinstance(year, int) or year < 1:
raise ValueError("年份必须为大于0的整数")
if not isinstance(month, int) or month < 1 or month > 12:
raise ValueError("月份必须为1-12之间的整数")
if day is not None:
if not isinstance(day, int) or day < 1 or day > 31:
raise ValueError("日期必须为1-31之间的整数")
max_days = [31,29 if year % 4 == 0 and (year % 100 != 0 or year % 400 == 0) else 28,
31,30,31,30,31,31,30,31,30,31][month-1]
if day > max_days:
raise ValueError(f"{year}年{month}月最大日期为{max_days}日")
def _get_month_days(self) -> int:
"""获取当月天数"""
if self.month == 2:
return 29 if self._is_leap_year() else 28
return [31,28,31,30,31,30,31,31,30,31,30,31][self.month-1]
def _is_leap_year(self) -> bool:
"""判断是否为闰年"""
return self.year % 4 == 0 and (self.year % 100 != 0 or self.year % 400 == 0)
def _get_first_weekday(self) -> int:
"""获取当月第一天星期几(周一到周日对应0-6)"""
return datetime.date(self.year, self.month, 1).weekday()
def _get_lunar_str(self, solar_date: datetime.date) -> str:
"""获取农历日期字符串"""
lunar = lunardate.LunarDate.fromSolarDate(solar_date.year, solar_date.month, solar_date.day)
month_str = (
f"闰{self.LUNAR_MONTHS[lunar.month]}"
if lunar.isLeapMonth
else self.LUNAR_MONTHS[lunar.month]
)
return f"{month_str}{self.LUNAR_DAYS[lunar.day]}" if lunar.day == 1 else self.LUNAR_DAYS[lunar.day]
def generate(self) -> dict:
"""
生成日历数据
:return: 包含完整日历数据的字典结构
"""
calendar_matrix = []
current_day = 1
for week_num in range(6):
week = []
for weekday in range(7):
pos = week_num * 7 + weekday
if pos < self._first_weekday or current_day > self._solar_days:
week.append(None)
else:
date = datetime.date(self.year, self.month, current_day)
week.append({
"solar_day": current_day,
"lunar_day": self._get_lunar_str(date),
"is_current_month": True,
"weekday": weekday,
"date": date.isoformat(),
"is_selected": self.day == current_day if self.day is not None else False
})
current_day += 1
calendar_matrix.append(week)
return {
"year": self.year,
"month": self.month,
"day": self.day,
"total_days": self._solar_days,
"weeks": calendar_matrix,
"lunar_month": self._get_lunar_month_str()
}
def _get_lunar_month_str(self) -> str:
"""获取农历月份描述"""
try:
lunar = lunardate.LunarDate.fromSolarDate(self.year, self.month, 1)
return (
f"闰{self.LUNAR_MONTHS[lunar.month]}"
if lunar.isLeapMonth
else self.LUNAR_MONTHS[lunar.month]
)
except:
return ""
if __name__ == "__main__":
calendar = LunarSolarCalendar(2025, 3, 15)
data = calendar.generate()
print(f"\n{data['year']}年{data['month']}月(农历{data['lunar_month']})")
print("周一 周二 周三 周四 周五 周六 周日")
print("-" * 42)
for week in data["weeks"]:
solar_line = ""
lunar_line = ""
for day in week:
if day:
solar_line += f"{day['solar_day']:4d} "
lunar_line += f"{day['lunar_day']:<6}"
else:
solar_line += " "
lunar_line += " "
print(solar_line)
print(lunar_line)
print()