📄 lunar.js
字号:
n = this.QB.substr( Math.floor((jd-f2)/365.2422*24),1 ); //找定气修正值
}else{
D = Math.floor( this.so_low( Math.floor((jd+pc-2451551)/29.5306) * Math.PI*2 ) +0.5 ); //2451551是2000.1.7的那个朔日,黄经差为0.定朔计算
n = this.SB.substr( Math.floor((jd-f2)/29.5306),1 ); //找定朔修正值
}
if(n=="1") return D+1;
if(n=="2") return D-1;
return D;
}
},
//排月序(生成实际年历),在调用calcY()后得到以下数据
//时间系统全部使用北京时,即使是天象时刻的输出,也是使用北京时
//如果天象的输出不使用北京时,会造成显示混乱,更严重的是无法与古历比对
leap:0, //闰月位置
ym:new Array(), //各月名称
ZQ:new Array(), //中气表,其中.liqiu是节气立秋的儒略日,计算三伏时用到
HS:new Array(), //合朔表
dx:new Array(), //各月大小
calcY:function(jd){ //农历排月序计算,可定出农历,有效范围:两个冬至之间(冬至一 <= d < 冬至二)
var A=this.ZQ, B=this.HS; //中气表,日月合朔表(整日)
var i, k, W, w;
//该年的中气
W = int2( (jd-355+183)/365.2422 )*365.2422+355; //355是2000.12冬至,得到较靠近jd的冬至估计值
if(this.calc(W,'气')>jd) W-=365.2422;
for(i=0;i<25;i++) A[i]=this.calc(W+15.2184*i,'气'); //25个节气时刻(北京时间),从冬至开始到下一个冬至以后
A.pe1=this.calc(W-15.2,'气'); A.pe2=this.calc(W-30.4,'气'); //被算二气,确保一年中年有月份的“气”全部被计算在内
//今年"首朔"的日月黄经差w
w = this.calc(A[0],'朔'); //求较靠近冬至的朔日
if(w>A[0]) w -= 29.53;
//该年所有朔,包含14个月的始末
for(i=0;i<15;i++) B[i]=this.calc(w+29.5306*i,'朔');
//月大小
this.leap = 0;
for(i=0;i<14;i++){
this.dx[i] = this.HS[i+1]-this.HS[i]; //月大小
this.ym[i]=i; //月序初始化
}
//-721年至-104年的后九月及月建问题,与朔有关,与气无关
var YY = int2( (this.ZQ[0]+10 +180)/365.2422) + 2000; //确定年份
if( YY>=-721 && YY <=-104 ){
var ly,b0,k0,lName,x0; //ly为历元(本历首月的儒略数),x0月建,lName闰月名称,b0,k0为置闰拟合参数
if(YY>=-721) ly=1457698-J2000, k0=12.368422, b0=0.342, lName='十三', x0=2; //春秋历,ly为-722.12.17
if(YY>=-479) ly=1546083-J2000, k0=12.368422, b0=0.500, lName='十三', x0=2; //战国历,ly为-480.12.11
if(YY>=-220) ly=1640641-J2000, k0=12.369000, b0=0.866, lName='后九', x0=11; //秦汉历,ly为-221.10.31;
nY = int2( (this.HS[0]-ly+100)/365.25 ); //年积数
var f1 = int2(b0+nY*k0), f2 = int2(b0+nY*k0+k0), f3; //f1有本年首的月积数,f2为下一年首的月积数
f1 = int2(f1); f2 = int2(f2);
for(i=0;i<14;i++){
f3 = int2( (this.HS[i]-ly+15)/29.5306 ); //该月积数
if(f3 < f2) f3 -= f1; else f3 -= f2;
if(f3 < 12) this.ym[i] = obb.ymc[(f3+x0)%12]; else this.ym[i] = lName;
}
return;
}
//无中气置闰法确定闰月,(气朔结合法,数据源需有冬至开始的的气和朔)
if( B[13] <= A[24] ){ //第13月的月末没有超过冬至(不含冬至),说明今年含有13个月
for(i=1; B[i+1]>A[2*i] && i<13; i++); //在13个月中找第1个没有中气的月份
this.leap = i;
for(;i<14;i++) this.ym[i]--;
}
//名称转换(月建别名)
for(i=0;i<14;i++){
var Dm = this.HS[i]+J2000, v2=this.ym[i]; //Dm初一的儒略日,v2为月建序号
var mc = obb.ymc[v2%12]; //月建对应的默认月名称:建子十一,建丑十二,建寅为正……
if ( Dm>=1724360 && Dm<=1729794 ) mc = obb.ymc[(v2+1)%12]; // 8.01.15至 23.12.02 建子为十二,其它顺推
else if( Dm>=1807724 && Dm<=1808699 ) mc = obb.ymc[(v2+1)%12]; //237.04.12至239.12.13 建子为十二,其它顺推
else if( Dm>=1999349 && Dm<=1999467 ) mc = obb.ymc[(v2+2)%12]; //761.12.02至762.03.30 建子为正月,其它顺推
else if( Dm>=1973067 && Dm<=1977112 ){if(v2%12==0) mc="正"; if(v2==2) mc='一';} //689.12.18至701.01.14 建子为正月,建寅为一月,其它不变
if(Dm==1729794||Dm==1808699) mc='拾贰'; //239.12.13及23.12.02均为十二月,为避免两个连续十二月,此处改名
this.ym[i]=mc;
}
}
};
SSQ.init();
/*********************************
以下是月历表的具体实现方法
*********************************/
/*********************************
=====以下是公历、农历、回历综合日历计算类=====
Lunar:日历计算物件
使用条件:事先引用eph.js天文历算文件
实例创建: var lun = new Lunar();
一、 yueLiCalc(By,Bm)方法
·功能:算出该月每日的详信息
·入口参数:
By是年(公历)
Bm是月(公历)
·返回:
lun.w0= (Bd0 + J2000 +1)%7; //本月第一天的星期
lun.y 公历年份
lun.m 公历月分
lun.d0 月首儒略日数
lun.dn 月天数
lun.Ly 干支纪年
lun.ShX 该年对应的生肖
lun.nianhao 年号纪年
lun.lun[] 各日信息(对象),日对象尊守此脚本程序开始的注释中定义
二、yueLiHTML(By,Bm)方法
·功能:算出该月每日的详细信息,并给出HTML月历表
·入口参数:
By是年(公历)
Bm是月(公历)
·返回:
yueLiCalc(By,Bm)返回的信息
lun.pg0 年份信息
lun.pg1 月历表
lun.pg2 月相节气表
**********************************/
//月历类件
function Lunar(){
var i;
this.lun=new Array();
for(i=0;i<31;i++) this.lun[i] = new Object();
this.lun.dn=0;
this.substr2=function(s,n,end){ //截串(网页设计对过长的文字做截处理)
s=s.replace(/(^\s*)|(\s*$)/g, "");
if(s.length>n+1) return s.substr(0,n)+end;
return s;
};
//返回公历某一个月的'公农回'三合历
this.yueLiCalc=function(By,Bm){
var i,j,k,c,Bd0,Bdn;
//日历物件初始化
JD.h=12, JD.m=0, JD.s=0.1;
JD.Y=By; JD.M=Bm; JD.D=1; Bd0 = int2(JD.toJD()) - J2000; //公历月首,中午
JD.M++; if(JD.M>12) JD.Y++,JD.M=1; Bdn = int2(JD.toJD()) - J2000 - Bd0; //本月天数(公历)
this.w0= (Bd0 + J2000 +1)%7; //本月第一天的星期
this.y = By; //公历年份
this.m = Bm; //公历月分
this.d0 =Bd0;
this.dn= Bdn;
//所属公历年对应的农历干支纪年
c = By -1984 + 9000;
this.Ly = obb.Gan[c%10]+obb.Zhi[c%12]; //干支纪年
this.ShX = obb.ShX[c%12]; //该年对应的生肖
this.nianhao = obb.getNH(By);
var D,w,ob,ob2;
//提取各日信息
for(i=0,j=0;i<Bdn;i++){
ob = this.lun[i];
ob.d0 = Bd0+i; //儒略日,北京时12:00
ob.di = i; //公历月内日序数
ob.y = By; //公历年
ob.m = Bm; //公历月
ob.dn = Bdn; //公历月天数
ob.week0 = this.w0; //月首的星期
ob.week = (this.w0+i)%7; //当前日的星期
ob.weeki = int2((this.w0+i)/7); //本日所在的周序号
ob.weekN = int2((this.w0+Bdn-1)/7) + 1; //本月的总周数
JD.setFromJD(ob.d0+J2000); ob.d = JD.D; //公历日名称
//农历月历
if(!SSQ.ZQ.length || ob.d0<SSQ.ZQ[0] || ob.d0>=SSQ.ZQ[24]) //如果d0已在计算农历范围内则不再计算
SSQ.calcY(ob.d0);
var mk = int2( (ob.d0-SSQ.HS[0])/30 ); if(mk<13 && SSQ.HS[mk+1]<=ob.d0) mk++; //农历所在月的序数
ob.Ldi = ob.d0 - SSQ.HS[mk]; //距农历月首的编移量,0对应初一
ob.Ldc = obb.rmc[ob.Ldi]; //农历日名称
ob.cur_dz = ob.d0-SSQ.ZQ[0]; //距冬至的天数
ob.cur_xz = ob.d0-SSQ.ZQ[12]; //距夏至的天数
ob.cur_lq = ob.d0-SSQ.ZQ[15]; //距立秋的天数
ob.cur_mz = ob.d0-SSQ.ZQ[11]; //距芒种的天数
ob.cur_xs = ob.d0-SSQ.ZQ[13]; //距小暑的天数
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -