万年历---java算法实现
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
万年历---java算法实现
万年历是我在网上见到的一份极高高精度的万年历,其采用先进的算法实现,其精度堪比刘安国教授为中国科学院国家授时中心制作的日梭万年历。但网络上只有javascript 版本。于是自己将其翻译为java程序,并公布于此,方便大家使用。
本文中讲的万年历是一款采用现代天文算法制作的农历历算程序,含有公历与回历信息,可以很方便的进行公、农、回三历之间的转换。提供公元-4712年到公元9999年的日期查询功能。其中1500年到1940农历数据已经与陈垣的《二十史朔闰表》核对;含有从公420元(南北朝/宋武帝元年)到今的基本年号。在过去几百年中,寿星万年历的误差是非常小的,节气时刻计算及日月合朔时刻的平均误差小于1秒,太阳坐标的最大可能误差为0.2角秒,月亮坐标的最大可能误差为3角秒,平均误差为误差的1/6。万年历中含有几百个国内城市的经纬度,并且用户可根据自已的需要扩展经纬度数据。
代码如下:
/**
* @author lxslove
* @mail moodlxs at 163
*
*/
public class SolarTerm {
// ========角度变换===============
private static final double rad = 180 * 3600 / Math.PI; // 每弧度的角秒数
private static final double RAD = 180 / Math.PI; // 每弧度的角度数
// ================日历计算===============
private static final double J2000 = 2451545; // 2000年前儒略日数(2000-1-1
// 12:00:00格林威治平时)
// =========黄赤交角及黄赤坐标变换===========
private static final double hcjjB[] = { 84381.448, -46.8150, -0.00059,
0.001813 };// 黄赤交角系数表
private static final double preceB[] = { 0, 50287.92262, 111.24406,
0.07699, -0.23479, -0.00178, 0.00018, 0.00001 };// Date黄道上的岁差p
private double Y = 2000;
private double M = 1;
private double D = 1;
private double h = 12;
private double m = 0;
private double s = 0;
private static final double[] 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 };
// 取整数部分
public static double int2(double v) {
v = Math.floor(v);
if (v < 0)
return v + 1;
return v;
}
// 对超过0-2PI的角度转为0-2PI
public static double rad2mrad(double v) {
v = v % (2 * Math.PI);
if (v < 0)
return v + 2 * Math.PI;
return v;
}
// 计算世界时与原子时之差,传入年
public double deltatT(double y) {
int i = 0;
for (i = 0; i < 100; i += 5)
if (y < dts[i + 5] || i == 95)
break;
double t1 = (y - dts[i]) / (dts[i + 5] - dts[i]) * 10;
double t2 = t1 * t1;
double t3 = t2 * t1;
return dts[i + 1] + dts[i + 2] * t1 + dts[i + 3] * t2 + dts[i + 4] * t3;
}
// 传入儒略日(J2000起算),计算UTC与原子时的差(单位:日)
public double deltatT2(double jd) {
return this.deltatT(jd / 365.2425 + 2000) / 86400.0;
}
// 公历转儒略日,UTC=1表示原日期是UTC
public double toJD(boolean UTC) {
double y = this.Y; // 取出年月
double m = this.M;
double n = 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)
return n + this.deltatT2(n - J2000);