http://www.truevue.org/blog/julian-date

儒略日(Julian Date)是在各个历法转换中常用的参数,那么什么是儒略日(Julian Date),儒略日(Julian Date)又怎么计算?

儒略日(Julian Date)的定义:

儒略日(Julian day,JD)是指由公元前4713年1月1日,协调世界时中午12时开始所经过的天数,多为天文学家采用,用以作为天文学的单一历法,把不同历法的年表统一起来。如果计算相隔若干年两个日期之间的天数,利用儒略日就比较方便。

 

儒略日(Julian Date)来历

  儒略日是由法国学者Joseph Justus Scliger(1540-1609)在1583年所创,这名称是为了纪念他的父亲——意大利学者Julius Caesar Scaliger(1484-1558)。

  儒略日的起点订在公元前4713年(天文学上记为 -4712 年)1月1日格林威治时间平午(世界时12:00),即JD 0 指定为 4713 B.C. 1月1日12:00 UT到4713 B.C. 1月2日12:00 UT的24小时。每一天赋予了一个唯一的数字,顺数而下,如:1996年1月1日12:00:00的儒略日是2450084。这个日期是考虑了太阳、月亮的运行周期,以及当时收税的间隔而订出来的。Joseph Scliger定义儒略周期为7980年,是因28、19、15的最小公倍数为28×19×15=7980。其中:

  28年为一太阳周期(solar cycle),经过一太阳周期,则星期的日序与月的日序会重复。

  19年为一太阴周期,或称默冬章(Metonic cycle),因235朔望月=19回归年,经过一太阴周期则阴历月年的日序重复。

  15年为一小纪(indiction cycle),此为罗马皇帝君士坦丁(Constantine)所颁,每15年评定财产价值以供课税,成为古罗马用的一个纪元单位,

  故以7980年为一儒略周期,而所选的起点公元前4713年,则是这三个循环周期同时开始的最近年份。

儒略日的计算

a=[(14-month)/12]
y=year+4800-a
m=month+12a-3

则格里历日期的中午时候

JDN=day+[(153m+2)/5]+365y+[y/4]-[y/100]+[y/400]-32045

若日期为儒略历,则

JDN=day+[(153m+2)/5]+365y+[y/4]-32083

儒略日(Julian Date)的简化:

由于儒略日数字位数太多,国际天文学联合会于1973年采用简化儒略日(MJD),其定义为 MJD = JD - 2400000.5。MJD相应的起点是1858年11月17日世界时0时。 例如1979年10月1日零时儒略日数为2,444,147.5。天文年历附表载有各年每月零日世界时12时的儒略日数。

 

====================

 

http://blog.163.com/permanier@126/blog/static/131097378200910232350472/

Qt库里CBSDate类的内部实现用_jd成员进行计算、比较等操作,而这个变量是通过static inline uint32 greg2jul(const int32 y, const int32 m, const int32 d)函数计算出来的。对于这个变量具体代表的含义,我弄不明白,在java里似乎也没发现直接对应的方法。尤其最终的计算表达式:

1721119 + day + (146097*c)/4 + (1461*ya)/4 + (153*month+2)/5;

这么多常数是什么含义???google了一下请教了朋友,大致明白了

这个计算,是算出一个日期对应的儒略日(Julian Date)。

儒略日是一种不用年和月的长期纪日法,计算距一个7980年周期的开始已逝去的天数,这个周期是1583年Joseph Scaliger发明的。这个系统的目的是要使计算一个日历日期和另一个日历日期之间的整数差变得容易。而7980年的周期是从取多个传统时间周期(太阳的,月亮的,还有一个很特殊的罗马的征税周期)的公倍数而得来的。第一个Julian周期的开始点是在儒略历的公元前4713年的一月一号格林尼治平午(即该地民用时12时,而不是平常的子夜开始),此时为“0”日的开始,至次日格林尼治平午为“1”日的开始,由此顺数而下,延续不断地记下来。第一个周期结束于3268年1月22号。接下来的那天就是第二个儒略日周期(7980年的周期)的第一天。

例如:

2451919.3423000001348555,它意味着距儒略周期的开始已经逝去了2451919天。“.3423000001348555”代表这天的时间(“15:12:54 EST”)。

 

儒略日的计算和使用:

公历转换为干支历

先看年干支的计算。在y年,如2005年则是y=2005;而公元前的年代要转为负号年代,如公元前2070年则为y=-2069。计算a值:a=y-4;再计算gz值:gz=a-[a/60]*60,其中[ ]表明是取整运算,如[8.75]=8。如果gz值为负,则gz=gz+60,使其为正值。这个gz值就是六十甲子的编号。例如,对2005年,y=2005,a=2001,a/60=33.35,[a/60]=33,gz=21,而21就是乙酉,说明2005年是乙酉年。对公元前2070年,y= -2069,a= -2073,a/60= -34.55,[a/60]= -34,gz= -33,gz= -33+60=27,则前2070年为辛卯年。

也可以从a值分别计算年天干或年地支。天干值为:g=a-[a/10]*10,若g是负数则g=g+10。地支值为:z=a-[a/12]*12,若z是负数则z=z+12。例如,公元前2070年,a= -2073,g = -3,g=7,z= -9,z=3。g值为7对应天干的“辛”,z值为3对应地支的“卯”,因此前2070年为辛卯年。

再看日干支的计算,主要是先将公历日期转换为儒略日,再由儒略日来计算日干支。因为儒略日是以正午开始新的一天,这里我们不妨约定某日的儒略日是对应于该日正午的。而计算儒略日的方法有很多种,这里只选一种适于编程的方法(括号内的是举例):

1)对于y年m月d日。(如2005年2月9日12时,则y = 2005,m = 2,d=9)

2)如果是1月和2月(m=1和m=2)则:m=m+12,y=y-1。(因m=2,则m=14,y=2004)

3)计算a值:a=[30.6001*(m+1)] 。(a=[30.6001*(14+1)]=[459.0015]=459)

4)计算b值:在1582年10月4日以前(含),b=0;在1582年10月15日以后(含),b=2-[y/100]+[y/400]。(因在1582年之后,b=2-[2004/100]+[2004/400]=2-20+5= -13)

5)计算c值:如果y<0,c=[365.25*y-0.75]-694025;如果y=0,c=[365.25*y-0.75]-694025;如果y>0,c=[365.25*y]-694025。(因y>0,c=[365.25*2004]-694025=731961-694025=37936)

6)计算约化儒略日mjd值(以1900年1月0.5日起算的天数):mjd=a+b+c+d。(mjd=459-13+37936+9=38391)

7)计算儒略日jd值: jd=mjd+2415020。(jd=38391+2415020=2453411)

从举例来看,2005年2月9日12时的儒略日为2453411,或略去12时而称2005年2月9日的儒略日为2453411。在计算儒略日时,对于公元前的年代,同样要注意先将其转为负号年代。

而将儒略日转换为日干支就非常简单了。对于儒略日jd值,计算ad值:ad=jd-11;再计算gz值:gz=ad-[ad/60]*60,这就是干支编号。例如儒略日为2453411,则ad=2453400,gz=0,对应干支为甲子,表明该日为甲子日。也可以从ad值分别计算日天干或日地支。天干值为:g=ad-[ad/10]*10,地支值为:z=ad-[ad/12]*12。

顺便提一句,用儒略日来计算星期几也很容易。对于儒略日jd值,计算ax值,ax=jd+1;再计算xq值:xq=ax-[ax/7]*7,xq值为0时是星期日,其余的值是几就是星期几。如2005年2月9日的儒略日为2453411,ax=2453412,xq=3,则该日为星期三。

而在java中,没有直接对应的计算儒略日的方法。。。java内部是使用unix的习惯,以1970年1月1日零时起经过的毫秒数来计算的。一般计算两个时间之间相隔天数,是

    long beginTime = beginDate.getTime();

    long endTime2 = endDate.getTime();

    long betweenDays = (long)((endTime - beginTime) / (1000 * 60 * 60 *24) + 0.5);

 

转者注:我要用的类库需要mjd时间。不得不google下了。

 

btw:儒略历转公历的算法。

double jd = mjd;//+2400000.5;

//计算year month,date
 int Y,M,D,hour,min,sec;
 int l= (int)jd + 68569;
 int N = ( 4 * l ) / 146097;
 l = l - ( 146097 *N + 3 ) / 4;
 int I = ( 4000 * ( l + 1 ) ) / 1461001;
 l = l - ( 1461 * I ) / 4 + 31;
 int J = ( 80 * l) / 2447;
 D = l - ( 2447 * J ) / 80;
 l = J / 11;
 M = J +2 - ( 12 *l );
 Y = 100 * ( N - 49 ) + I + l;

//计算hour minute second

 double hms = jd - (int)jd;
 hour = (int)(hms*24.0);
 min = (int)((hms - hour/24.0)*1440.0);
 sec = (int)((hms-hour/24.0-min/1444.0)*86400.0);

 

Logo

前往低代码交流专区

更多推荐