本文目录导读:

我来为你提供几种不同方式的农历公历转换脚本实现方案。
使用 lunardate 库(Python)
这是最简单的方法,使用 lunardate 库:
import lunardate
# 公历转农历
def solar_to_lunar(year, month, day):
try:
lunar = lunardate.LunarDate.fromSolarDate(year, month, day)
return (lunar.year, lunar.month, lunar.day, lunar.isLeapMonth)
except Exception as e:
return f"转换失败: {e}"
# 农历转公历
def lunar_to_solar(lunar_year, lunar_month, lunar_day, is_leap=False):
try:
solar = lunardate.LunarDate(lunar_year, lunar_month, lunar_day, is_leap).toSolarDate()
return (solar.year, solar.month, solar.day)
except Exception as e:
return f"转换失败: {e}"
# 使用示例
if __name__ == "__main__":
# 公历 2024-01-01 转农历
print(solar_to_lunar(2024, 1, 1)) # 输出: (2023, 11, 20, False) 即农历2023年冬月二十
# 农历 2024-01-01 转公历
print(lunar_to_solar(2024, 1, 1)) # 输出: (2024, 2, 10) 即公历2024年2月10日(春节)
自实现算法(纯 Python)
这是一个简单但功能完整的实现:
# 农历数据表(1900-2100年,每个月大小月和闰月信息)
# 每4个字节表示一年:12位表示每月大小月,4位表示闰月编号,4位表示闰月大小月
lunar_info = [
0x04bd8, 0x04ae0, 0x0a570, 0x054d5, 0x0d260, 0x0d950, 0x16554, 0x056a0, 0x09ad0, 0x055d2, # 1900-1909
0x04ae0, 0x0a5b6, 0x0a4d0, 0x0d250, 0x1d255, 0x0b540, 0x0d6a0, 0x0ada2, 0x095b0, 0x14977, # 1910-1919
0x04970, 0x0a4b0, 0x0b4b5, 0x06a50, 0x06d40, 0x1ab54, 0x02b60, 0x09570, 0x052f2, 0x04970, # 1920-1929
0x06566, 0x0d4a0, 0x0ea50, 0x06a95, 0x05ad0, 0x02b60, 0x186e3, 0x092e0, 0x1c8d7, 0x0c950, # 1930-1939
0x0d4a0, 0x1d8a6, 0x0b550, 0x056a0, 0x1a5b4, 0x025d0, 0x092d0, 0x0d2b2, 0x0a950, 0x0b557, # 1940-1949
0x06ca0, 0x0b550, 0x15355, 0x04da0, 0x0a5b0, 0x14573, 0x052b0, 0x0a9a8, 0x0e950, 0x06aa0, # 1950-1959
0x0aea6, 0x0ab50, 0x04b60, 0x0aae4, 0x0a570, 0x05260, 0x0f263, 0x0d950, 0x05b57, 0x056a0, # 1960-1969
0x096d0, 0x04dd5, 0x04ad0, 0x0a4d0, 0x0d4d4, 0x0d250, 0x0d558, 0x0b540, 0x0b6a0, 0x195a6, # 1970-1979
0x095b0, 0x049b0, 0x0a974, 0x0a4b0, 0x0b27a, 0x06a50, 0x06d40, 0x0af46, 0x0ab60, 0x09570, # 1980-1989
0x04af5, 0x04970, 0x064b0, 0x074a3, 0x0ea50, 0x06b58, 0x05ac0, 0x0ab60, 0x096d5, 0x092e0, # 1990-1999
0x0c960, 0x0d954, 0x0d4a0, 0x0da50, 0x07552, 0x056a0, 0x0abb7, 0x025d0, 0x092d0, 0x0cab5, # 2000-2009
0x0a950, 0x0b4a0, 0x0baa4, 0x0ad50, 0x055d9, 0x04ba0, 0x0a5b0, 0x15176, 0x052b0, 0x0a930, # 2010-2019
0x07954, 0x06aa0, 0x0ad50, 0x05b52, 0x04b60, 0x0a6e6, 0x0a4e0, 0x0d260, 0x0ea65, 0x0d530, # 2020-2029
0x05aa0, 0x076a3, 0x096d0, 0x04afb, 0x04ad0, 0x0a4d0, 0x0d0b6, 0x0d250, 0x0d520, 0x0dd45, # 2030-2039
0x0b5a0, 0x056d0, 0x055b2, 0x049b0, 0x0a577, 0x0a4b0, 0x0aa50, 0x1b255, 0x06d20, 0x0ada0, # 2040-2049
]
# 天干地支
TIAN_GAN = ['甲', '乙', '丙', '丁', '戊', '己', '庚', '辛', '壬', '癸']
DI_ZHI = ['子', '丑', '寅', '卯', '辰', '巳', '午', '未', '申', '酉', '戌', '亥']
SHENG_XIAO = ['鼠', '牛', '虎', '兔', '龙', '蛇', '马', '羊', '猴', '鸡', '狗', '猪']
LUNAR_MONTH = ['正', '二', '三', '四', '五', '六', '七', '八', '九', '十', '冬', '腊']
LUNAR_DAY = ['初一', '初二', '初三', '初四', '初五', '初六', '初七', '初八', '初九', '初十',
'十一', '十二', '十三', '十四', '十五', '十六', '十七', '十八', '十九', '二十',
'廿一', '廿二', '廿三', '廿四', '廿五', '廿六', '廿七', '廿八', '廿九', '三十']
class LunarCalendar:
def __init__(self):
self.lunar_info = lunar_info
def _get_lunar_month_days(self, lunar_year, lunar_month):
"""获取农历某月天数"""
leap_month = self._get_leap_month(lunar_year)
if leap_month == lunar_month:
return 30 if self._get_leap_month_days(lunar_year) else 29
info = self.lunar_info[lunar_year - 1900]
return 30 if (info & (0x10000 >> lunar_month)) else 29
def _get_leap_month(self, lunar_year):
"""获取农历年闰月"""
return self.lunar_info[lunar_year - 1900] >> 16 & 0xf
def _get_leap_month_days(self, lunar_year):
"""获取农历年闰月天数"""
return self.lunar_info[lunar_year - 1900] & 0x10000
def solar_to_lunar(self, year, month, day):
"""公历转农历"""
# 计算输入日期距离 1900-01-31 的天数
base_date = [1900, 1, 31]
offset = self._day_from_1900(year, month, day) - self._day_from_1900(*base_date)
if offset < 0:
return None
# 计算农历年份
lunar_year = 1900
while offset > 0:
days = self._get_lunar_year_days(lunar_year)
offset -= days
if offset >= 0:
lunar_year += 1
if offset < 0:
offset += days
lunar_year -= 1
# 计算农历月份
lunar_month = 1
leap_month = self._get_leap_month(lunar_year)
is_leap = False
while offset > 0:
if lunar_month == leap_month and not is_leap:
days = 30 if self._get_leap_month_days(lunar_year) else 29
if offset >= days:
offset -= days
if offset == 0:
is_leap = True
else:
break
lunar_month += 1
else:
days = self._get_lunar_month_days(lunar_year, lunar_month)
if offset >= days:
offset -= days
lunar_month += 1
else:
break
# 计算农历日期
lunar_day = offset + 1
return (lunar_year, lunar_month, lunar_day, is_leap)
def lunar_to_solar(self, lunar_year, lunar_month, lunar_day, is_leap=False):
"""农历转公历"""
# 计算该年农历天数
days = 0
# 计算到目标月份之前的天数
leap_month = self._get_leap_month(lunar_year)
for month in range(1, lunar_month):
if month == leap_month and not is_leap:
days += 30 if self._get_leap_month_days(lunar_year) else 29
else:
days += self._get_lunar_month_days(lunar_year, month)
# 处理闰月
if is_leap and lunar_month == leap_month:
days += 30 if self._get_leap_month_days(lunar_year) else 29
# 加上当前月的天数
if is_leap and lunar_month == leap_month:
days += lunar_day
else:
days += lunar_day
# 从1900-01-31算起
base_date = [1900, 1, 31]
offset = days
# 计算公历日期
return self._date_from_1900(self._day_from_1900(*base_date) + offset)
def _get_lunar_year_days(self, year):
"""获取农历年总天数"""
# 这里简化计算,实际需要根据农历数据表计算
info = self.lunar_info[year - 1900]
total = 0
for month in range(1, 13):
total += 30 if (info & (0x10000 >> month)) else 29
leap_month = info >> 16 & 0xf
if leap_month:
total += 30 if info & 0x10000 else 29
return total
def _day_from_1900(self, year, month, day):
"""计算从1900年1月0日开始的天数"""
days = 0
for y in range(1900, year):
days += 366 if self._is_leap_year(y) else 365
for m in range(1, month):
days += self._get_month_days(year, m)
return days + day
def _date_from_1900(self, days):
"""从1900年1月0日开始计算公历日期"""
year = 1900
while days > 0:
year_days = 366 if self._is_leap_year(year) else 365
if days <= year_days:
break
days -= year_days
year += 1
month_days = [31, 29 if self._is_leap_year(year) else 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
month = 1
for m in range(12):
if days <= month_days[m]:
month = m + 1
break
days -= month_days[m]
return (year, month, days)
def _is_leap_year(self, year):
"""判断是否为闰年"""
return year % 4 == 0 and (year % 100 != 0 or year % 400 == 0)
def _get_month_days(self, year, month):
"""获取公历月份天数"""
if month in [1, 3, 5, 7, 8, 10, 12]:
return 31
elif month in [4, 6, 9, 11]:
return 30
else:
return 29 if self._is_leap_year(year) else 28
# 使用示例
if __name__ == "__main__":
calendar = LunarCalendar()
# 公历 2024-01-01 转农历
print(calendar.solar_to_lunar(2024, 1, 1))
# 农历 2024-01-01 转公历
print(calendar.lunar_to_solar(2024, 1, 1))
使用 chinese-calendar 库(推荐)
这个库更专业,功能更丰富:
pip install chinese-calendar
from chinese_calendar import lunar_to_solar, solar_to_lunar
from datetime import date
# 公历转农历
def solar_to_lunar_demo():
dt = date(2024, 1, 1)
lunar_date = solar_to_lunar(dt)
print(f"公历 2024-01-01 对应农历: {lunar_date.year}-{lunar_date.month}-{lunar_date.day}")
print(f"是否闰月: {lunar_date.is_leap_month}")
# 农历转公历
def lunar_to_solar_demo():
lunar_date = lunar_to_solar(2024, 1, 1)
print(f"农历 2024-01-01 对应公历: {lunar_date.year}-{lunar_date.month}-{lunar_date.day}")
if __name__ == "__main__":
solar_to_lunar_demo()
lunar_to_solar_demo()
JavaScript 版本
// lunarcalendar.js
class LunarCalendar {
constructor() {
// 农历数据表(同上)
this.lunarInfo = [
0x04bd8, 0x04ae0, 0x0a570, 0x054d5, 0x0d260, 0x0d950, 0x16554, 0x056a0, 0x09ad0, 0x055d2,
// ... 完整数据需从Python版本复制
];
this.TIAN_GAN = ['甲', '乙', '丙', '丁', '戊', '己', '庚', '辛', '壬', '癸'];
this.DI_ZHI = ['子', '丑', '寅', '卯', '辰', '巳', '午', '未', '申', '酉', '戌', '亥'];
// ... 其他常量
}
solarToLunar(year, month, day) {
// 实现逻辑与Python版本相同
// 这里简化处理,实际需要完整实现
const baseDate = new Date(1900, 0, 31); // JS中月份从0开始
const targetDate = new Date(year, month - 1, day);
const offset = Math.floor((targetDate - baseDate) / (24 * 60 * 60 * 1000));
// 根据偏移量计算农历日期
// 需要完整实现
return { year: 0, month: 0, day: 0, isLeap: false };
}
lunarToSolar(lunarYear, lunarMonth, lunarDay, isLeap = false) {
// 实现逻辑与Python版本相同
// 需要完整实现
return { year: 0, month: 0, day: 0 };
}
}
// 使用示例
const calendar = new LunarCalendar();
console.log(calendar.solarToLunar(2024, 1, 1));
安装和使用建议
-
推荐使用
chinese-calendar库(如果只需要基本功能) -
如果需要完整功能,使用
lunardate库 -
如果不想依赖外部库,使用自实现算法
-
注意闰月处理:实现时要特别注意闰月的判断
这些实现应该能满足大部分农历公历转换的需求,如果还有具体问题,欢迎继续询问!
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播