别再手动算农历了!用Python的sxtwl库,5分钟搞定你的传统节日提醒机器人
用Python打造智能农历节日提醒系统:sxtwl库实战指南
每次春节前手忙脚乱查放假安排?总在节气当天才想起该吃饺子?传统节日对现代人来说越来越像彩蛋——不期而遇。其实用Python的sxtwl库加上30行代码,就能让这些特殊日期自动跳进你的日程表。下面我会带你从零构建一个会"算命"的智能提醒机器人,它不仅能告诉你下一个节气是哪天,还能提前三天发微信提醒你准备艾草浴。
1. 为什么需要农历智能提醒系统
公历日程管理工具遍地都是,但涉及到农历就集体失灵。我去年就曾因为记错农历生日,把家庭聚会订在了真实生日的前一周。更不用说那些固定在农历某日的传统节日——春节、端午、中秋,每年对应的公历日期都像在玩捉迷藏。
sxtwl这个冷门库恰好解决了这个问题。它不仅支持农历与公历的互转,还能直接查询节气、干支甚至星座。结合Python的自动化能力,我们可以实现:
- 提前N天提醒重要农历节日(可自定义提醒间隔)
- 节气当日早晨推送养生建议(比如"今日大暑,宜绿豆汤")
- 自动生成年度农历节日日历(方便提前规划)
- 企业微信/钉钉机器人通知(避免被邮件淹没)
# 安装核心库
pip install sxtwl schedule requests
提示:sxtwl最新版可能存在部分星座计算bug,建议固定安装2.0.6版本
2. 系统核心架构设计
这个提醒系统的关键在于三个模块的配合:
- 时间计算引擎:sxtwl负责所有农历相关计算
- 调度系统:schedule库实现每日自动检查
- 通知系统:根据场景选择邮件、企业微信或短信
graph TD
A[每日定时触发] --> B{今天是节日/节气吗?}
B -->|是| C[发送提醒]
B -->|否| D[计算下一个节日]
D --> E[设置临时提醒任务]
表:农历提醒系统状态转换逻辑
| 组件 | 功能说明 | 备选方案 |
|---|---|---|
| sxtwl | 农历日期计算与节气判断 | zhdate(功能较少) |
| schedule | 定时任务调度 | APScheduler |
| 企业微信机器人 | 通知推送 | 邮件/SMS/钉钉 |
3. 核心代码实现
先实现一个农历日期查询工具类,后续所有功能都基于这些基础方法:
import sxtwl
class LunarCalendar:
def __init__(self):
self.jqmc = ["冬至", "小寒", "大寒", "立春", "雨水", "惊蛰",
"春分", "清明", "谷雨", "立夏", "小满", "芒种",
"夏至", "小暑", "大暑", "立秋", "处暑", "白露",
"秋分", "寒露", "霜降", "立冬", "小雪", "大雪"]
def get_today_info(self):
"""获取今日农历信息"""
day = sxtwl.fromSolar(2023, 8, 15) # 实际使用应替换为datetime.now()
info = {
'lunar_date': f"{day.getLunarYear()}年{day.getLunarMonth()}月{day.getLunarDay()}日",
'solar_date': f"{day.getSolarYear()}年{day.getSolarMonth()}月{day.getSolarDay()}日",
'jieqi': self.jqmc[day.getJieQi()] if day.hasJieQi() else None
}
return info
测试这个基础功能:
calendar = LunarCalendar()
print(calendar.get_today_info())
# 输出示例: {'lunar_date': '2023年6月29日', 'solar_date': '2023年8月15日', 'jieqi': None}
接下来实现节日判断逻辑。我们需要先定义重要的传统节日:
class FestivalReminder:
FESTIVALS = {
"春节": {"month": 1, "day": 1, "advance_days": 7},
"端午": {"month": 5, "day": 5, "advance_days": 3},
"中秋": {"month": 8, "day": 15, "advance_days": 3},
"冬至": {"is_jieqi": True, "advance_days": 1}
}
def check_festival(self, lunar_info):
today = lunar_info['lunar_date']
for name, config in self.FESTIVALS.items():
if config.get('is_jieqi'):
if lunar_info['jieqi'] == name:
return name
else:
if today.month == config['month'] and today.day == config['day']:
return name
return None
4. 实现自动化提醒
现在把各个模块串联起来,实现完整的自动化流程:
import schedule
import time
from datetime import datetime
class AutoReminder:
def __init__(self):
self.calendar = LunarCalendar()
self.reminder = FestivalReminder()
def daily_check(self):
today = datetime.now()
lunar_info = self.calendar.get_today_info()
festival = self.reminder.check_festival(lunar_info)
if festival:
self.send_notification(f"今天是{lunar_info['lunar_date']},{festival}快乐!")
def send_notification(self, message):
# 实际项目中替换为真实的通知发送逻辑
print(f"[通知] {message}")
def run(self):
schedule.every().day.at("08:00").do(self.daily_check)
while True:
schedule.run_pending()
time.sleep(60)
if __name__ == "__main__":
bot = AutoReminder()
bot.run()
对于需要提前多天提醒的场景,可以扩展check_festival方法:
def check_upcoming_festivals(self, days_ahead=7):
upcoming = []
for i in range(1, days_ahead + 1):
future_date = datetime.now() + timedelta(days=i)
lunar_info = self.calendar.get_solar_date(future_date.year,
future_date.month,
future_date.day)
festival = self.check_festival(lunar_info)
if festival:
upcoming.append((future_date.strftime("%Y-%m-%d"), festival))
return upcoming
5. 高级功能扩展
基础功能实现后,可以考虑这些增强功能:
-
多平台通知集成:
- 企业微信机器人Webhook
- 钉钉自定义机器人
- 短信网关(适合重要提醒)
-
智能提醒规则:
# 根据节日类型设置不同提醒规则 REMINDER_RULES = { '春节': {'first_remind': 30, 'second_remind': 7, 'channel': 'sms'}, '清明': {'remind': 3, 'channel': 'wechat'}, '立夏': {'remind': 1, 'channel': 'email'} } -
历史数据统计:
def get_year_festivals(self, year): """获取某年所有重要节日日期""" festivals = {} for month in range(1, 13): for day in range(1, 30): lunar_day = sxtwl.fromLunar(year, month, day) solar_date = f"{lunar_day.getSolarYear()}-{lunar_day.getSolarMonth()}-{lunar_day.getSolarDay()}" festival = self.check_festival({ 'lunar_date': lunar_day, 'jieqi': self.jqmc[lunar_day.getJieQi()] if lunar_day.hasJieQi() else None }) if festival: festivals[solar_date] = festival return festivals -
生日提醒特别处理:
def add_birthday_reminder(self, name, lunar_month, lunar_day): """添加农历生日提醒""" self.birthdays.append({ 'name': name, 'month': lunar_month, 'day': lunar_day })
6. 部署与优化建议
实际部署时,有几个实用技巧值得分享:
-
错误处理:sxtwl在处理极端日期时可能报错,需要捕获异常
try: day = sxtwl.fromSolar(2200, 2, 30) # 不存在的日期 except Exception as e: print(f"日期转换错误: {e}") -
性能优化:频繁创建sxtwl对象会影响性能,可以缓存常用日期
from functools import lru_cache @lru_cache(maxsize=365) def get_day_info(year, month, day): return sxtwl.fromSolar(year, month, day) -
时区处理:节气精确到分钟级别,需要考虑服务器时区
import pytz from datetime import datetime tz = pytz.timezone('Asia/Shanghai') now = datetime.now(tz) -
日志记录:所有提醒操作应该记录日志便于排查
import logging logging.basicConfig(filename='reminder.log', level=logging.INFO)
这个项目最让我惊喜的是sxtwl对干支纪年的支持。有次我突发奇想,给系统加了个功能:每天推送晨间问候时附带当天的天干地支。结果这个"封建迷信"功能意外地受欢迎,团队成员都开始用"今天是癸卯年丙辰月"来替代普通的日期表达。
更多推荐


所有评论(0)