Bootstrap

JavaScript实战 - 农历(阴历)和公历(阳历)之间的转换 - 第二弹 基于算法的实现

作者:逍遥Sean
简介:一个主修Java的Web网站\游戏服务器后端开发者
主页:https://blog.csdn.net/Ureliable
觉得博主文章不错的话,可以三连支持一下~ 如有需要我的支持,请私信或评论留言!

前言:

接续上篇JavaScript实战 - 农历(阴历)和公历(阳历)之间的转换

前篇的代码只是一个简单的转换历法思路
本篇我将为您展示一个更完整的农历(阴历)和公历(阳历)之间的转换方法。
这种转换涉及到复杂的历法计算和数据源获取,需要考虑到闰年、闰月以及特殊节气等因素。
我将提供一个基于算法的实现示例,而非简单的数据表查找方法。

JavaScript实战 - 农历(阴历)和公历(阳历)之间的转换 基于算法的实现

农历转公历(阴历转阳历)

// 农历转公历函数
function lunarToSolar(lunarYear, lunarMonth, lunarDay) {
    // 农历年份对应的基准公历日期
    const baseYear = 1900;
    const baseMonth = 1;
    const baseDay = 31; // 农历1900年正月初一对应的公历日期

    // 公历1900年正月初一的JD值(Julian Day)
    const baseJD = 2415020.5;

    // 计算农历年份到公历年份之间的总天数
    let totalDays = 0;
    for (let year = baseYear; year < lunarYear; year++) {
        totalDays += daysInYear(year); // 计算每一年的天数总和
    }

    // 加上该年农历月份前面的月份的天数
    for (let month = 1; month < lunarMonth; month++) {
        totalDays += daysInMonth(lunarYear, month);
    }

    // 加上农历日期对应的天数
    totalDays += lunarDay - 1; // 农历日从1开始,转换为0开始的索引

    // 计算对应的公历日期的JD值
    let solarJD = baseJD + totalDays;
    
    // 转换为公历日期
    let date = jdToDate(solarJD);
    
    return {
        year: date.year,
        month: date.month,
        day: date.day
    };
}

// 计算某一年的总天数(公历)
function daysInYear(year) {
    if (isLeapYear(year)) {
        return 366;
    } else {
        return 365;
    }
}

// 判断某一年是否是闰年(公历)
function isLeapYear(year) {
    return (year % 4 === 0 && year % 100 !== 0) || (year % 400 === 0);
}

// 计算某一年某一月的天数(公历)
function daysInMonth(year, month) {
    if (month === 2) {
        return isLeapYear(year) ? 29 : 28;
    } else if ([4, 6, 9, 11].includes(month)) {
        return 30;
    } else {
        return 31;
    }
}

// 将JD值转换为公历日期
function jdToDate(jd) {
    let Z = Math.floor(jd + 0.5);
    let W = Math.floor((Z - 1867216.25) / 36524.25);
    let X = Math.floor(W / 4);
    let A = Z + 1 + W - X;
    let B = A + 1524;
    let C = Math.floor((B - 122.1) / 365.25);
    let D = Math.floor(365.25 * C);
    let E = Math.floor((B - D) / 30.6001);
    let day = B - D - Math.floor(30.6001 * E);
    let month = E < 14 ? E - 1 : E - 13;
    let year = month > 2 ? C - 4716 : C - 4715;

    return {
        year: year,
        month: month,
        day: day
    };
}

// 示例调用
const lunarYear = 2024;
const lunarMonth = 6;
const lunarDay = 15;
const solarDate = lunarToSolar(lunarYear, lunarMonth, lunarDay);
console.log(`农历 ${lunarYear}${lunarMonth}${lunarDay}日 对应的公历日期是:${solarDate.year}${solarDate.month}${solarDate.day}`);

公历转农历(阳历转阴历)

这部分的算法较为复杂,涉及到从公历日期计算到农历日期的转换,包括闰年的判断和每年的闰月情况。以下是一个基本的示例:

// 公历转农历函数
function solarToLunar(solarYear, solarMonth, solarDay) {
    // 计算公历日期的JD值
    const solarJD = dateToJD(solarYear, solarMonth, solarDay);

    // 计算从公历1900年1月31日到该公历日期的总天数
    const baseYear = 1900;
    const baseMonth = 1;
    const baseDay = 31;
    const baseJD = 2415020.5; // 公历1900年1月31日对应的JD值

    let totalDays = solarJD - baseJD;

    // 农历年份
    let lunarYear = baseYear;

    // 计算农历年份
    while (true) {
        let daysOfYear = daysInYear(lunarYear);
        if (totalDays < daysOfYear) {
            break;
        }
        totalDays -= daysOfYear;
        lunarYear++;
    }

    // 农历月份
    let lunarMonth = 1;
    let isLeap = false;

    // 计算农历月份和日期
    while (true) {
        let daysOfMonth = daysInMonth(lunarYear, lunarMonth);
        if (totalDays < daysOfMonth) {
            break;
        }
        totalDays -= daysOfMonth;
        lunarMonth++;
    }

    return {
        lunarYear: lunarYear,
        lunarMonth: lunarMonth,
        lunarDay: totalDays + 1 // 农历日期从1开始
    };
}

// 将公历日期转换为JD值
function dateToJD(year, month, day) {
    let A = Math.floor((14 - month) / 12);
    let Y = year + 4800 - A;
    let M = month + 12 * A - 3;
    let JD = day + Math.floor((153 * M + 2) / 5) + 365 * Y + Math.floor(Y / 4) - 32083;

    return JD - 0.5; // 返回JD值
}

// 示例调用
const solarYear = 2024;
const solarMonth = 7;
const solarDay = 26;
const lunarDate = solarToLunar(solarYear, solarMonth, solarDay);
console.log(`公历 ${solarYear}${solarMonth}${solarDay}日 对应的农历日期是:${lunarDate.lunarYear}${lunarDate.lunarMonth}${lunarDate.lunarDay}`);

注意事项

  • 精度问题:这些示例是基于简化的算法和公式,实际应用中可能需要更复杂的计算来处理闰年、闰月、节气等特殊情况。
  • 数据源:在实际开发中,可以通过更详细和精确的历法数据来实现更准确的转换。

在实际应用中,您可能需要根据具体需求和环境进一步优化和调整算法。

;