JavaScript农历与公历转换算法实现

Ivy
Ivy
发布时间:2026-10-13 | 2人浏览过
原创

在网页开发中,日历类应用经常需要处理农历与公历的对应关系。由于农历是阴阳合历,其置闰规则(十九年七闰)较为复杂。本文分享一段基于 JavaScript 的经典转换代码,通过核心数据表 lunarInfo 配合数学算法,即可在客户端轻松完成 1891-2100 年的日期双向换算。

转换原理与数据结构

农历转换的核心在于掌握每一年的历法特征。该算法使用一个预定义的数据数组 lunarInfo,存储了从 1891 年到 2100 年每年的关键信息。每一年由一个包含四个数字的数组表示,例如:[闰月月份, 正月天数, 正月初一对应的公历日期, 月份二进制数据]。

lunarInfo 中的后三位数字通常以十进制存储,但在实际处理时,最后一个数字会被转换为 16 位的二进制数。这个二进制序列的每一位代表该农历年中对应月份的大小:'1' 代表大月(30天),'0' 代表小月(29天)。通过这种压缩方式,可以高效地判断任意月份的准确天数。

核心功能实现步骤

第1步:配置基础年份范围

确定转换的有效区间。代码中定义了 MIN_YEAR : 1891 和 MAX_YEAR : 2100,这覆盖了绝大多数现代应用场景的需求范围。超出此范围的日期需要进行额外的逻辑扩展或提示用户。

第2步:初始化公历计算辅助函数

首先确保公历部分计算准确。系统实现了 isLeapYear 方法来判断闰年,进而通过 solarMonthDays 获取公历各月的天数(特别是二月是 28 还是 29 天)。这是进行“农历转公历”时的基准参照。

第3步:实现公历转农历(toLunar)

当需要将公历日期(如 2016-07-06)转换为农历时,算法执行以下逻辑:

  1. 定位基准日:查询当年对应的 lunarInfo,找到该年正月初一对应的公历日期(即 yearData[1] 月和 yearData[2] 日)。
  2. 计算天数差:利用 Date 对象计算目标公历日期与正月初一之间的天数差值(betweenSolarDays)。
  3. 映射农历日期:根据天数差,在当年的农历月份序列中累加查找,确定具体的农历月份(t)和日期(e)。
  4. 处理闰月:如果计算的月份恰好是当年的闰月,则在月份名称前添加“闰”字(如“闰五月”)。
  5. 格式化输出:最后将数字形式的年月日转换为中文形式(如“二零二三年 九月 十五”)以及干支纪年。

第4步:实现农历转公历(toSolar)

反向转换(如输入农历 2016-6-3 查公历)的流程如下:

  1. 获取农历天数偏移量:调用 betweenLunarDays,通过遍历当年的月份数据,计算目标农历日期距离该年正月初一的天数总和。
  2. 计算时间戳偏移:基于正月初一对应的公历日期,加上上一步计算出的天数差(转换为毫秒),得到目标日期的时间戳。
  3. 解析公历结果:利用 JavaScript 的 Date 对象解析该时间戳,从而直接提取出公历的年、月、日数值。

完整代码示例

以下是整合好的 Lunar 对象代码。你可以直接将其嵌入项目中,并通过 Lunar.toSolar(年, 月, 日) 和 Lunar.toLunar(年, 月, 日) 调用接口。注意闰月的传入规则:若某年有闰月,第二个该月份需传为“闰月+1”后的序号(例如闰五月则传 6 月)。

var Lunar = {
  MIN_YEAR : 1891,
  MAX_YEAR : 2100,
  // lunarInfo: 历年数据,此处省略具体数组内容以保持简洁
  lunarInfo : [
    // ... 完整的历年数据数组 ...
  ],
  isLeapYear : function(year) {
    return ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0));
  },
  solarMonthDays : function(year, month) {
    var FebDays = this.isLeapYear(year) ? 29 : 28;
    var monthHash = ['', 31, FebDays, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
    return monthHash[month];
  },
  toLunar : function(year, month, day) {
    var yearData = this.lunarInfo[year - this.MIN_YEAR];
    if (year == this.MIN_YEAR && month <= 2 && day <= 9) {
      return [1891, 1, 1, '辛卯', '兔', '正月', '初一'];
    }
    return this.lunarByBetween(year, this.betweenSolarDays(year, month, day, yearData[1], yearData[2]));
  },
  toSolar : function(year, month, day) {
    var yearData = this.lunarInfo[year - this.MIN_YEAR];
    var between = this.betweenLunarDays(year, month, day);
    var ms = new Date(year +"-" + yearData[1] +"-"+ yearData[2]).getTime();
    var s = ms + between * 24 * 60 * 60 * 1000;
    var d = new Date();
    d.setTime(s);
    year = d.getFullYear();
    month = d.getMonth() + 1;
    day  = d.getDate();
    return [year, month, day];
  },
  // ... 其他内部计算方法(如 chineseNumber, betweenLunarDays 等)请参照完整源码 ...
};

以上就是JavaScript农历与公历相互转换的详细内容,更多关于JavaScript日期处理的技巧资料请关注本站其它相关文章!

相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表