万年历java算法实现.docx
《万年历java算法实现.docx》由会员分享,可在线阅读,更多相关《万年历java算法实现.docx(21页珍藏版)》请在冰豆网上搜索。
万年历java算法实现
万年历---java算法实现
万年历是我在网上见到的一份极高高精度的万年历,其采用先进的算法实现,其精度堪比刘安国教授为中国科学院国家授时中心制作的日梭万年历。
但网络上只有javascript版本。
于是自己将其翻译为java程序,并公布于此,方便大家使用。
本文中讲的万年历是一款采用现代天文算法制作的农历历算程序,含有公历与回历信息,可以很方便的进行公、农、回三历之间的转换。
提供公元-4712年到公元9999年的日期查询功能。
其中1500年到1940农历数据已经与陈垣的《二十史朔闰表》核对;含有从公420元(南北朝/宋武帝元年)到今的基本年号。
在过去几百年中,寿星万年历的误差是非常小的,节气时刻计算及日月合朔时刻的平均误差小于1秒,太阳坐标的最大可能误差为0.2角秒,月亮坐标的最大可能误差为3角秒,平均误差为误差的1/6。
万年历中含有几百个国内城市的经纬度,并且用户可根据自已的需要扩展经纬度数据。
代码如下:
/**
*@authorlxslove
*@mail moodlxsat163
*
*/
publicclassSolarTerm{
//========角度变换===============
privatestaticfinaldoublerad=180*3600/Math.PI;//每弧度的角秒数
privatestaticfinaldoubleRAD=180/Math.PI;//每弧度的角度数
//================日历计算===============
privatestaticfinaldoubleJ2000=2451545;//2000年前儒略日数(2000-1-1
//12:
00:
00格林威治平时)
//=========黄赤交角及黄赤坐标变换===========
privatestaticfinaldoublehcjjB[]={84381.448,-46.8150,-0.00059,
0.001813};//黄赤交角系数表
privatestaticfinaldoublepreceB[]={0,50287.92262,111.24406,
0.07699,-0.23479,-0.00178,0.00018,0.00001};//Date黄道上的岁差p
privatedoubleY=2000;
privatedoubleM=1;
privatedoubleD=1;
privatedoubleh=12;
privatedoublem=0;
privatedoubles=0;
privatestaticfinaldouble[]dts={
//世界时与原子时之差计算表
-4000,108371.7,-13036.80,392.000,0.0000,-500,17201.0,
-627.82,16.170,-0.3413,-150,12200.6,-346.41,5.403,-0.1593,
150,9113.8,-328.13,-1.647,0.0377,500,5707.5,-391.41,0.915,
0.3145,900,2203.4,-283.45,13.034,-0.1778,1300,490.1,-57.35,
2.085,-0.0072,1600,120.0,-9.81,-1.532,0.1403,1700,10.2,
-0.91,0.510,-0.0370,1800,13.4,-0.72,0.202,-0.0193,1830,
7.8,-1.81,0.416,-0.0247,1860,8.3,-0.13,-0.406,0.0292,1880,
-5.4,0.32,-0.183,0.0173,1900,-2.3,2.06,0.169,-0.0135,1920,
21.2,1.69,-0.304,0.0167,1940,24.2,1.22,-0.064,0.0031,1960,
33.2,0.51,0.231,-0.0109,1980,51.0,1.29,-0.026,0.0032,2000,
64.7,-1.66,5.224,-0.2905,2150,279.4,732.95,429.579,0.0158,
6000};
//取整数部分
publicstaticdoubleint2(doublev){
v=Math.floor(v);
if(v<0)
returnv+1;
returnv;
}
//对超过0-2PI的角度转为0-2PI
publicstaticdoublerad2mrad(doublev){
v=v%(2*Math.PI);
if(v<0)
returnv+2*Math.PI;
returnv;
}
//计算世界时与原子时之差,传入年
publicdoubledeltatT(doubley){
inti=0;
for(i=0;i<100;i+=5)
if(y break;
doublet1=(y-dts[i])/(dts[i+5]-dts[i])*10;
doublet2=t1*t1;
doublet3=t2*t1;
returndts[i+1]+dts[i+2]*t1+dts[i+3]*t2+dts[i+4]*t3;
}
//传入儒略日(J2000起算),计算UTC与原子时的差(单位:
日)
publicdoubledeltatT2(doublejd){
returnthis.deltatT(jd/365.2425+2000)/86400.0;
}
//公历转儒略日,UTC=1表示原日期是UTC
publicdoubletoJD(booleanUTC){
doubley=this.Y;//取出年月
doublem=this.M;
doublen=0;
if(m<=2){
m+=12;
y--;
}
if(this.Y*372+this.M*31+this.D>=588829){
//判断是否为格里高利历日1582*372+10*31+15
n=int2(y/100);
n=2-n+int2(n/4);//加百年闰
}
n+=int2(365.2500001*(y+4716));//加上年引起的偏移日数
n+=int2(30.6*(m+1))+this.D;//加上月引起的偏移日数及日偏移数
n+=((this.s/60+this.m)/60+this.h)/24-1524.5;
if(UTC)
returnn+this.deltatT2(n-J2000);
returnn;
}
//儒略日数转公历,UTC=1表示目标公历是UTC
publicvoidsetFromJD(doublejd,booleanUTC){
if(UTC)
jd-=this.deltatT2(jd-J2000);
jd+=0.5;
//取得日数的整数部份A及小数部分F
doubleA=int2(jd);
doubleF=jd-A;
doubleD;
if(A>2299161){
D=int2((A-1867216.25)/36524.25);
A+=1+D-int2(D/4);
}
A+=1524;//向前移4年零2个月
this.Y=int2((A-122.1)/365.25);//年
D=A-int2(365.25*this.Y);//去除整年日数后余下日数
this.M=int2(D/30.6001);//月数
this.D=D-int2(this.M*30.6001);//去除整月日数后余下日数
this.Y-=4716;
this.M--;
if(this.M>12)
this.M-=12;
if(this.M<=2)
this.Y++;
//日的小数转为时分秒
F*=24;
this.h=int2(F);
F-=this.h;
F*=60;
this.m=int2(F);
F-=this.m;
F*=60;
this.s=F;
}
//设置时间,参数例:
"20000101120000"或"20000101"
publicvoidsetFromStr(Strings){
this.Y=Double.parseDouble(s.substring(0,4));
this.M=Double.parseDouble(s.substring(4,2));
this.D=Double.parseDouble(s.substring(6,2));
this.h=Double.parseDouble(s.substring(9,2));
this.m=Double.parseDouble(s.substring(11,2));
this.s=Double.parseDouble(s.substring(13,2));/*将5改为了2*/
}
//日期转为串
publicStringtoStr(){
StringY=" "+(int)this.Y;
StringM="0"+(int)this.M;
StringD="0"+(int)this.D;
doubleh=this.h,m=this.m,s=Math.floor(this.s+.5);
if(s>=60){
s-=60;
m++;
}
if(m>=60){
m-=60;
h++;
}
Stringsh="0"+(int)h,sm="0"+(int)m,ss="0"+(int)s;
Y=Y.substring(Y.length()-5,Y.lengt