儒略日的计算

儒略日的计算

现在的公历起源于埃及历,由古罗马的恺撒在公元前46年制定的,365
日作为一年,单月为大月31天,双月为小月30天,4年一闰,称为"儒略历"或"恺撒历"。
1582年罗马教皇格里高利十三世(Gregorius XⅢ)对"儒略历"又进行修改,规定被4
整除的年为闰年,但逢百之年只有能被400
除尽才能是闰年。这就是使用至今的"格里历"。教皇于1582年10月 4
日还下令将次日(即原10月5日)定为10月15日,把春分日又恢复为3月21日。


儒略日(Julian day,JD)是由法国学者 Joseph Justus Scaliger(1540-1609
)发明的,是天文学上不用一种不用年、月的长期纪日法,用它可以很方便地计算到两时?
涞慵湟蕴焓屏康氖奔浼涓簟H迓匀找怨?713年儒略历1月1
日格林威治平午为起算日期,以7980
年为一个周期,每天顺数而下,流水计日。儒略日的这种计算方法相当方便,获得了天文?
缒诘囊恢虏捎茫翘煳募扑阒凶钗匾募扑慊肌?


例如:JD=245 191 9.34230,它意味着距儒略周期的开始已经逝去了2451919
天。而小数点后的".34230"代表这天的时间("15:12:54 EST")
,在天体位置计算中是最具信息量的数据。再比如世界时公元2009年3月1号的儒略日是
2454891.8333333335天。

注意,"儒略日(julian Day)" 与"儒略历(Julian Calendar)"指的不是同一概念。


由于儒略日的表达数值太长,需要7
位数字表示天数,因此,后来又出现了一种约化儒略日(Modified Julian Day,MJD
)的记法,MJD = JD - 2,400,000.5,即约化儒略日的起算点在1858年11月16
日平午。之所以采用约化儒略日的表达方法,主要有一下2个方面的考虑:

1.日期天数的计算往往习惯以午夜时分起算,而不是正午。

2.在1859至2130年之间,只需要5位数字来表示日期就够了,而不需要全部的7位数字

因此MJD 0就等于JD 2400000.5。对于计算机来说,MJD也意味着更少的存储单元


下面介绍几种儒略日的计算方法:

(一):求出给定年(I),月(J),日(K)的儒略日:
JD=K-32075+1461*(I+4800+ (J-14)/12)/4+367*(J-2-(J-14)/12*12)/12-3*((I+4900+(J-
14)/12)/100)/4

貌似很简单的样子,baidu搜索来之,没用过,不知如何处理1582年那消失的10天。
(二):根据Fundamental Astronomy上介绍的算法,c语言表述:

float jde(int Y,int M,int D,int hour,int min,int sec)
{
    long int f,g,mid1,mid2;
    float J,JDE,A;
    if(M>=3)
    {
        f=Y;
        g=M;
    }
    if(M==1||M==2)
    {
        f=Y-1;
        g=M=12;
    };
    mid1=floor(365.25*f);
    mid2=floor(30.6001*(g+1));
    A=2-floor(f/100)+floor(f/400);
    J=mid1+mid2+D+A+1720994.5;
    JDE=J+hour/24+min/1440+sec/86400;
    return JDE;
};

上述函数返回float类型可能精度不够,最好用double类型。


(三)Jean Meeus的《天文算法》(Astronomical Algorithms,2nd Edition
)第二版中第7章第60页内有详细介绍计算儒略日的方法:

设Y为给定年份,M为月份,D
为该月日期(带小数,把时:分:秒折算成日的形式)。运算符INT
表示为取所给数的整数部分,也即小数点前的部分。

1.若M > 2,Y和M不变。

若 M =1或2,以Y-1代Y,以M+12代M。

换句话说,如果日期在1月或2月,则被看作是在前一年的13月或14月。

2.对格里高利历(即1582年10月15日以后),有

A = INT(Y/100),

B = 2 - A + INT(A/4).

另外,对于儒略历(即1582年10月15日之前),取B=0。

3.所求的儒略日即为:


因为处理器的字长问题,计算机不能精确表示 30.6,比如当5乘30.6刚好是153
,而在处理器内部却表示成152.999 999 8的结果,会使取整操作(INT
)与预期不符,故用30.6001代替30.6,以期得到正确的结果(事实上,30.601甚至30.61
亦可)。

以下列的是一个著名的星图软件stellarium里内对于Jean Meeus
所介绍的方法的实际代码,个人比较推荐:
double get_julian_day (const ln_date * cdate)
{
    ln_date date;
    int y, m, B;

    date = *cdate;

    y = date.years;
    m = date.months;
    if (date.months <= 2)
    {
        y = date.years - 1;
        m = date.months + 12;
    }

    // Correct for the lost days in Oct 1582 when the Gregorian calendar
    // replaced the Julian calendar.
    B = -2;
    if (date.years > 1582 || (date.years == 1582 && (date.months > 10 || (date
.months == 10 && date.days >= 15))))
    {
        B = y / 400 - y / 100;
    }

    return (floor(365.25 * y) +
            floor(30.6001 * (m + 1)) + B + 1720996.5 +
            date.days + date.hours / 24.0 + date.minutes / 1440.0 + date.
seconds / 86400.0);
}
其中结构体date定义如下:
typedef struct
{
    int years;         /*!< Years. All values are valid */
    int months;        /*!< Months. Valid values : 1 (January) - 12 (December
) */
    int days;         /*!< Days. Valid values 1 - 28,29,30,31 Depends on month
.*/
    int hours;         /*!< Hours. Valid values 0 - 23. */
    int minutes;     /*!< Minutes. Valid values 0 - 59. */
    double seconds;    /*!< Seconds. Valid values 0 - 59.99999.... */
}ln_date;
上述代码是0.8版本的source code,在julian_day.c
文件内。在该文件内,还有一个从儒略日JD反推日期、时间的函数,很强大。stellarium
目前最新的版本是0.10.2,最近刚release,可以在我前面给的链接内找到下载。

(四)下面是一个计算儒略日的JavaScript:
function compute(form) {
    MM=eval(form.nmonth.value);
    DD=eval(form.nday.value);
    YY=eval(form.nyear.value);
    HR=eval(form.nhour.value);
    MN=eval(form.nminute.value);
    SC=eval(form.nsecond.value);
    with (Math) {
      HR = HR + (MN / 60) + (SC/3600);
      GGG = 1;
      if (YY <= 1585) GGG = 0;
      JD = -1 * floor(7 * (floor((MM + 9) / 12) + YY) / 4);
      S = 1;
      if ((MM - 9)<0) S=-1;
      A = abs(MM - 9);
      J1 = floor(YY + S * floor(A / 7));
      J1 = -1 * floor((floor(J1 / 100) + 1) * 3 / 4);
      JD = JD + floor(275 * MM / 9) + DD + (GGG * J1);
      JD = JD + 1721027 + 2 * GGG + 367 * YY - 0.5;
      JD = JD + (HR / 24);
    }
    form.result.value = JD;
}
function gettodayandnow(form) {
    var now = new Date();
    var hours = now.getUTCHours();
    var minutes = now.getUTCMinutes();
    var seconds = now.getUTCSeconds()
    var month = now.getUTCMonth() + 1;
    var day = now.getUTCDate();
    var year = now.getUTCFullYear();
    form.nmonth.value=month;
    form.nday.value=day;
    form.nyear.value=year;
    form.nhour.value=hours;
    form.nminute.value=minutes;
    form.nsecond.value=seconds;
}

(五)再来一个脚本程序:
function compute(form)
{
var y = parseFloat(form.year.value)
var m = parseFloat(form.month.value)
var d = parseFloat(form.day.value)
var uh = parseFloat(form.uth.value)
var um = parseFloat(form.utm.value)
var us = parseFloat(form.uts.value)

var extra = 100.0*y + m - 190002.5
var rjd = 367.0*y
rjd -= Math.floor(7.0*(y+Math.floor((m+9.0)/12.0))/4.0)
rjd += Math.floor(275.0*m/9.0)
rjd += d
rjd += (uh + (um + us/60.0)/60.)/24.0
rjd += 1721013.5
rjd -= 0.5*extra/Math.abs(extra)
rjd += 0.5
form.result.value = rjd-0.3333333333
}

posted @ 2011-03-14 14:51  郭—大—侠  阅读(3887)  评论(0编辑  收藏  举报