农历

101 阅读7分钟

const mArr = [ "春节", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月", ]; const dArr = [ "初二", "初三", "初四", "初五", "初六", "初七", "初八", "初九", "初十", "十一", "十二", "十三", "十四", "十五", "十六", "十七", "十八", "十九", "二十", "廿一", "廿一", "廿一", "廿一", "廿一", "廿一", "廿一", "廿一", "廿一", "三十", ]; /**

  • 根据农历获取阳历
  • @see blog.csdn.net/zhangjiaqia…
  • @param {农历日期, 2022-01-01} lunar
  • @param {是否闰月, false} leapMonthFlag
  • @return {阳历日期, 2022-02-01} newDate */ export const getSolarByLunar = (lunar, leapMonthFlag) => { // 使用//g正则替换所有 var lunarDt = lunar.replace(/-/g, ""); var lunarYear = parseInt(lunarDt.substring(0, 4)); var lunarMonth = parseInt(lunarDt.substring(4, 6)); var lunarDay = parseInt(lunarDt.substring(6, 8));

checkLunarDate(lunarYear, lunarMonth, lunarDay, leapMonthFlag);

var offset = 0; for (var i = 1900; i < lunarYear; i++) { var yearDaysCount = getYearDays(i); // 求阴历某年天数 offset += yearDaysCount; }

var leapMonth = getLeapMonth(lunarYear);

//当年没有闰月或月份早于闰月或和闰月同名的月份 if ( leapMonth == 0 || lunarMonth < leapMonth || !leapMonthFlag & (lunarMonth == leapMonth) ) { for (var i = 1; i < lunarMonth; i++) { var tempMonthDaysCount = getMonthDays(lunarYear, i); offset += tempMonthDaysCount; } // 检查日期是否大于最大天 if (lunarDay > getMonthDays(lunarYear, lunarMonth)) { console.error("不合法的农历日期!"); } offset += lunarDay; // 加上当月的天数 } else { console.log("当年有闰月,且月份晚于或等于闰月======" + leapMonth); //当年有闰月,且月份晚于或等于闰月 for (var i = 1; i < lunarMonth; i++) { var tempMonthDaysCount = getMonthDays(lunarYear, i); offset += tempMonthDaysCount; } if (lunarMonth > leapMonth) { var temp = getLeapMonthDays(lunarYear); // 计算闰月天数 offset += temp; // 加上闰月天数

  if (lunarDay > getMonthDays(lunarYear, lunarMonth)) {
    throw new Exception("不合法的农历日期!");
  }
  offset += lunarDay;
} else {
  // 如果需要计算的是闰月,则应首先加上与闰月对应的普通月的天数
  // 计算月为闰月
  var temp = getMonthDays(lunarYear, lunarMonth); // 计算非闰月天数
  offset += temp;

  if (lunarDay > getLeapMonthDays(lunarYear)) {
    throw new Exception("不合法的农历日期!");
  }
  offset += lunarDay;
}

}

// 阳历日期计算起点 var startStr = "1900-01-30"; var newDate = new Date(startStr); newDate.setDate(newDate.getDate() + offset); return newDate; }; /**

  • 根据阳历获取农历

  • @see www.iteye.com/blog/lixor-…

  • @param {当前日期} curDate

  • @returns {int数组 [1,2]} result:索引1代表天数,索引2代表月份 */ export const getLunarBySolar = (curDate) => { var leapMonth = 0; var date = new Date("1900/1/31"); // 求出当前时间和1900年1月31日相差的天数 var offset = parseInt((curDate.getTime() - date.getTime()) / 86400000); // 用offset减去每农历年的天数,计算当天是农历第几天,i最终结果是农历的年份,offset是当年的第几天 var iYear, daysOfYear = 0; for (iYear = 1900; iYear < 2100 && offset > 0; iYear++) { daysOfYear = getYearDays(iYear); offset -= daysOfYear; } if (offset < 0) { offset += daysOfYear; iYear--; } // 闰哪个月,1-12 leapMonth = getLeapMonth(iYear); var leap = false; // 默认值 // 用当年的天数offset,逐个减去每月(农历)的天数,求出当天是本月的第几天 var iMonth, daysOfMonth = 0; for (iMonth = 1; iMonth < 13 && offset > 0; iMonth++) { // 闰月 if (leapMonth > 0 && iMonth == leapMonth + 1 && !leap) { --iMonth; leap = true; daysOfMonth = getLeapMonthDays(iYear); } else daysOfMonth = getMonthDays(iYear, iMonth);

    offset -= daysOfMonth; // 解除闰月 if (leap && iMonth == leapMonth + 1) leap = false; } // offset为0时,并且刚才计算的月份是闰月,要校正 if (offset == 0 && leapMonth > 0 && iMonth == leapMonth + 1) { if (leap) { leap = false; } else { leap = true; --iMonth; } } // offset小于0时,也要校正 if (offset < 0) { offset += daysOfMonth; --iMonth; } // var result = []; // result.push(iMonth); // result.push(offset); return numberToChinaDay(iMonth, offset); }; const numberToChinaDay = (m, d) => { return d == 0 ? mArr[m - 1] : dArr[d - 1]; }; const checkLunarDate = (lunarYear, lunarMonth, lunarDay, leapMonthFlag) => { if (lunarYear < 1900 || lunarYear > 2100) { console.error("非法年份" + lunarYear); } if (lunarMonth < 1 || lunarMonth > 12) { console.error("非法月======" + lunarMonth); } if (lunarDay < 1 || lunarDay > 31) { console.error("非法天======" + lunarDay); } //计算该年闰几月 var leapMonth = getLeapMonth(lunarYear); if (leapMonthFlag & (leapMonth != lunarMonth)) { // console.error("非润月======"); } }; const getMonthDays = (lunarYeay, month) => { if (month > 31 || month < 0) { throw new Exception("月份有错!"); } // 0X0FFFF[0000 {1111 1111 1111} 1111]中间12位代表12个月,1为大月,0为小月 var bit = 1 << (16 - month); if ((lunarInfo[lunarYeay - 1900] & 0x0ffff & bit) == 0) { return 29; } else { return 30; } }; const getLeapMonthDays = (year) => { if (getLeapMonth(year) != 0) { if ((lunarInfo[year - 1900] & 0xf0000) == 0) { return 29; } else { return 30; } } else { return 0; } }; const lunarInfo = [ 0x04bd8, 0x04ae0, 0x0a570, 0x054d5, 0x0d260, 0x0d950, 0x16554, 0x056a0, 0x09ad0, 0x055d2, 0x04ae0, 0x0a5b6, 0x0a4d0, 0x0d250, 0x1d255, 0x0b540, 0x0d6a0, 0x0ada2, 0x095b0, 0x14977, 0x04970, 0x0a4b0, 0x0b4b5, 0x06a50, 0x06d40, 0x1ab54, 0x02b60, 0x09570, 0x052f2, 0x04970, 0x06566, 0x0d4a0, 0x0ea50, 0x06e95, 0x05ad0, 0x02b60, 0x186e3, 0x092e0, 0x1c8d7, 0x0c950, 0x0d4a0, 0x1d8a6, 0x0b550, 0x056a0, 0x1a5b4, 0x025d0, 0x092d0, 0x0d2b2, 0x0a950, 0x0b557, 0x06ca0, 0x0b550, 0x15355, 0x04da0, 0x0a5d0, 0x14573, 0x052d0, 0x0a9a8, 0x0e950, 0x06aa0, 0x0aea6, 0x0ab50, 0x04b60, 0x0aae4, 0x0a570, 0x05260, 0x0f263, 0x0d950, 0x05b57, 0x056a0, 0x096d0, 0x04dd5, 0x04ad0, 0x0a4d0, 0x0d4d4, 0x0d250, 0x0d558, 0x0b540, 0x0b5a0, 0x195a6, 0x095b0, 0x049b0, 0x0a974, 0x0a4b0, 0x0b27a, 0x06a50, 0x06d40, 0x0af46, 0x0ab60, 0x09570, 0x04af5, 0x04970, 0x064b0, 0x074a3, 0x0ea50, 0x06b58, 0x055c0, 0x0ab60, 0x096d5, 0x092e0, 0x0c960, 0x0d954, 0x0d4a0, 0x0da50, 0x07552, 0x056a0, 0x0abb7, 0x025d0, 0x092d0, 0x0cab5, 0x0a950, 0x0b4a0, 0x0baa4, 0x0ad50, 0x055d9, 0x04ba0, 0x0a5b0, 0x15176, 0x052b0, 0x0a930, 0x07954, 0x06aa0, 0x0ad50, 0x05b52, 0x04b60, 0x0a6e6, 0x0a4e0, 0x0d260, 0x0ea65, 0x0d530, 0x05aa0, 0x076a3, 0x096d0, 0x04bd7, 0x04ad0, 0x0a4d0, 0x1d0b6, 0x0d250, 0x0d520, 0x0dd45, 0x0b5a0, 0x056d0, 0x055b2, 0x049b0, 0x0a577, 0x0a4b0, 0x0aa50, 0x1b255, 0x06d20, 0x0ada0, ]; const getYearDays = (y) => { var i, sum = 348; for (i = 0x8000; i > 0x8; i >>= 1) { if ((lunarInfo[y - 1900] & i) != 0) sum += 1; } return sum + leapDays(y); }; const leapDays = (y) => { if (getLeapMonth(y) != 0) { if ((lunarInfo[y - 1900] & 0x10000) != 0) return 30; else return 29; } else return 0; }; const getLeapMonth = (y) => { return lunarInfo[y - 1900] & 0xf; };