松原市网站建设_网站建设公司_在线客服_seo优化
2025/12/31 10:21:32 网站建设 项目流程

在国内业务系统中,农历(阴历)仍然被广泛使用,例如:

  • 农历生日、纪念日
  • 传统节日(春节、除夕、中秋)
  • 日历 / 黄历 / 命理类应用
  • 本地化系统展示

本文基于lunar-python农历算法库,使用Flask封装了一套完整、可直接部署的农历转换 REST API,支持:

  • ✅ 公历 → 农历
  • ✅ 农历 → 公历(支持闰月)
  • ✅ 当前农历日期查询
  • ✅ 干支、生肖、节气、节日
  • ✅ 完整中文描述

支持时间范围:1900 – 2100 年


一、技术选型说明

1️⃣ lunar-python

选择lunar-python的原因:

  • 农历算法成熟、权威
  • API 设计清晰
  • 支持干支、生肖、节气、节日
  • 支持闰月(负数月份表示)
  • 纯 Python,无外部依赖
pipinstalllunar-python

2️⃣ Flask

  • 轻量
  • 易于部署
  • 非常适合工具型 API / 内部服务
pipinstallflask

二、API 设计说明

本示例实现了 4 个接口:

接口说明
/api/to_lunar公历 → 农历
/api/to_solar农历 → 公历(支持闰月)
/api/today_lunar获取当前农历
/服务状态 & 接口说明

三、核心设计:统一农历数据结构

为了方便前端或其他系统使用,先对lunar-python的返回结果进行统一格式化

农历信息格式化函数

defformat_lunar(lunar):"""统一格式化农历信息(完全适配 lunar_python 最新版)"""month=lunar.getMonth()# 可能为负数(闰月)is_leap_month=month<0abs_month=abs(month)festivals=lunar.getFestivals()# 标准农历节日other_festivals=lunar.getOtherFestivals()# 其他扩展节日return{"lunar_year":lunar.getYear(),"lunar_month":abs_month,"lunar_day":lunar.getDay(),"is_leap_month":is_leap_month,"chinese_string":lunar.toFullString(),"full_info":lunar.toFullString(),"ganzhi_year":lunar.getYearInChinese(),"ganzhi_month":lunar.getMonthInChinese(),"ganzhi_day":lunar.getDayInChinese(),"shengxiao":lunar.getYearShengXiao(),"jieqi":lunar.getJieQi()iflunar.getJieQi()elseNone,"festivals":festivalsiffestivalselseNone,"other_festivals":other_festivalsifother_festivalselseNone}

设计说明

  • 闰月判断month < 0

  • 节日区分

    • getFestivals():传统节日(春节、除夕)
    • getOtherFestivals():扩展节日
  • 输出结构稳定,方便前端直接使用


四、公历 → 农历 API

接口定义

GET /api/to_lunar

参数

参数说明
year公历年
month公历月
day公历日

代码实现

@app.route('/api/to_lunar',methods=['GET'])defto_lunar():try:year=int(request.args.get('year'))month=int(request.args.get('month'))day=int(request.args.get('day'))solar=Solar.fromYmd(year,month,day)lunar=solar.getLunar()returnjsonify({"success":True,"solar_date":f"{year}-{month:02d}-{day:02d}","lunar":format_lunar(lunar)})exceptExceptionase:returnjsonify({"success":False,"error":str(e)}),400

示例请求

/api/to_lunar?year=2025&month=2&day=1

五、农历 → 公历 API(支持闰月)

接口定义

GET /api/to_solar

参数

参数说明
year农历年
month农历月
day农历日
leap是否闰月(true / false)

关键点:闰月处理

lunar_month=-monthifleapelsemonth

这是lunar-python的标准用法。

代码实现

@app.route('/api/to_solar',methods=['GET'])defto_solar():try:year=int(request.args.get('year'))month=int(request.args.get('month'))day=int(request.args.get('day'))leap=request.args.get('leap','false').lower()in('true','1','yes')lunar_month=-monthifleapelsemonth lunar=Lunar.fromYmd(year,lunar_month,day)solar=lunar.getSolar()returnjsonify({"success":True,"lunar":format_lunar(lunar),"solar_date":solar.toYmd()})exceptExceptionase:returnjsonify({"success":False,"error":str(e)}),400

六、获取当前农历日期 API

接口定义

GET /api/today_lunar

代码实现

@app.route('/api/today_lunar',methods=['GET'])deftoday_lunar():try:now=datetime.now()today_solar=Solar.fromDate(now)today_lunar=today_solar.getLunar()returnjsonify({"success":True,"solar_date":today_solar.toYmd(),"solar_datetime":today_solar.toYmdHms(),"timestamp":now.isoformat(),"lunar":format_lunar(today_lunar)})exceptExceptionase:returnjsonify({"success":False,"error":str(e)}),500

适合:

  • 首页日历
  • 今日农历展示
  • 黄历 / 日签应用

七、服务启动与运行

if__name__=='__main__':app.run(host='0.0.0.0',port=5006,debug=True)

启动后访问:

http://localhost:5006/

即可看到接口说明。


八、返回 JSON 示例(简化)

{"lunar_year":2024,"lunar_month":12,"lunar_day":4,"is_leap_month":false,"chinese_string":"甲辰年 腊月初四","shengxiao":"龙","festivals":["春节"]}

完整代码

from flaskimportFlask, request, jsonify from lunar_pythonimportSolar, Lunar from datetimeimportdatetimeimporttraceback app=Flask(__name__)def format_lunar(lunar):"""统一格式化农历信息(完全适配 lunar_python 最新版)""" month=lunar.getMonth()# 可能为负数(闰月)is_leap_month=month<0abs_month=abs(month)festivals=lunar.getFestivals()# 标准农历节日(如春节、除夕)other_festivals=lunar.getOtherFestivals()# 其他扩展节日return{"lunar_year":lunar.getYear(),"lunar_month":abs_month,"lunar_day":lunar.getDay(),"is_leap_month":is_leap_month,"chinese_string":lunar.toFullString(),"full_info":lunar.toFullString(),"ganzhi_year":lunar.getYearInChinese(),"ganzhi_month":lunar.getMonthInChinese(),"ganzhi_day":lunar.getDayInChinese(),"shengxiao":lunar.getYearShengXiao(),"jieqi":lunar.getJieQi()iflunar.getJieQi()elseNone,"festivals":festivalsiffestivalselseNone,# 传统农历节日列表"other_festivals":other_festivalsifother_festivalselseNone# 其他节日}@app.route('/api/to_lunar',methods=['GET'])def to_lunar(): try: year=int(request.args.get('year'))month=int(request.args.get('month'))day=int(request.args.get('day'))solar=Solar.fromYmd(year, month, day)lunar=solar.getLunar()returnjsonify({"success":True,"solar_date":f"{year}-{month:02d}-{day:02d}","lunar":format_lunar(lunar)})except Exception as e: app.logger.error(f"Error in to_lunar: {str(e)}\n{traceback.format_exc()}")returnjsonify({"success":False,"error":str(e),"detail":str(e)}),400@app.route('/api/to_solar',methods=['GET'])def to_solar(): try: year=int(request.args.get('year'))month=int(request.args.get('month'))day=int(request.args.get('day'))leap=request.args.get('leap','false').lower()in('true','1','yes')lunar_month=-monthifleapelsemonth lunar=Lunar.fromYmd(year, lunar_month, day)solar=lunar.getSolar()returnjsonify({"success":True,"lunar":format_lunar(lunar),"solar_date":solar.toYmd()})except Exception as e: app.logger.error(f"Error in to_solar: {str(e)}\n{traceback.format_exc()}")returnjsonify({"success":False,"error":str(e),"detail":str(e)}),400@app.route('/api/today_lunar',methods=['GET'])def today_lunar(): try: app.logger.info("Calling /api/today_lunar")now=datetime.now()today_solar=Solar.fromDate(now)app.logger.info(f"Today solar: {today_solar.toYmd()} {today_solar.toYmdHms()}")today_lunar=today_solar.getLunar()returnjsonify({"success":True,"solar_date":today_solar.toYmd(),"solar_datetime":today_solar.toYmdHms(),"timestamp":now.isoformat(),"lunar":format_lunar(today_lunar)})except Exception as e: error_msg=str(e)tb=traceback.format_exc()app.logger.error(f"Error in today_lunar: {error_msg}\n{tb}")returnjsonify({"success":False,"error":"Internal Server Error","detail":error_msg,"traceback":tb}),500@app.route('/',methods=['GET'])def home():returnjsonify({"message":"Lunar Calendar API is running! (lunar_python fully adapted)","current_time":datetime.now().isoformat(),"endpoints":{"to_lunar":"/api/to_lunar?year=2025&month=12&day=24","to_solar":"/api/to_solar?year=2025&month=11&day=5&leap=false","today_lunar":"/api/today_lunar"}})if__name__=='__main__':app.run(host='0.0.0.0',port=5006,debug=True)

九、适用场景

  • 📅 日历 / 黄历系统
  • 🎂 农历生日管理
  • 🧧 中国本土化应用
  • 🌐 Web / 小程序后端
  • 🧰 内部工具 API

十、总结

本文基于lunar-python + Flask实现了一套:

功能完整、结构清晰、可直接部署的农历转换 API

特点:

  • 不依赖外部命令
  • 支持闰月
  • 返回结构友好
  • 易于扩展

非常适合用于实际生产项目

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询