儒略日與公曆轉換

儒略日是一種從曆元(公元前4213年1月1日正午12時)開始連續紀日的歷法,要換算其他曆法的公曆,一般以此爲中介。所以在曆法對比中經常要用到儒略日。[注1]

公曆轉儒略日

《Astronomical Algorithms》中給出了簡便的計算公式。[注2]

書中並未給出公式的含義,這裏做一個分析。

儒略曆轉儒略日

儒略日的本質是積日,若求Y年M月D日對應的儒略日,即分別對(Y-曆元年)年(M-1)月D日進行積日。

:現行公曆從公元前4713年開始,由於公元紀年法沒有0年,爲方便計算,天文學中以0表示公元前1年,則公元前4713年表示爲-4712。對儒略曆而言,以365.25天爲歲長,每年閏餘0.25天,4年閏餘1天則需置閏。故儒略曆每4年一閏,即對於365.25,每4年前3年向下取整,第四年向上取整。計算Y年的積日,即將從-4712年到Y年的積年乘以一迴歸年的長度。

int((Y+4712)*365.25)

:1.公曆設置大小月的基本思路是每月大小相間隔。相鄰兩月必爲61天,如此一年共366天。平均一月爲30.5天,對小月向下取整爲30(int(30.5)),大月則爲相鄰2個月日數減小月日數(int(30.5*2)-int(30.5))。這種情況下,M月(積月爲M-1)的積日即爲int(30.5*(M-1))。而公曆以單數月爲31天,雙數月爲30天。即歲首(M=1)時爲大月,可令上式M=M+1,再從該式中減去多算的一月30,則積日爲int(30.5*M)-30

2. 公曆一年實際只有365日,需在某月中減去一天,而公曆設在二月。這時,3~12月份仍然是有規律的(大小月相隔),1月有31天,2月有29天。如此,可假設以3月份作爲歲首,2月爲年尾。則在2月減去的一天可理解爲上年歲末(即今年歲首前)少一天。並以13、14月表示上一年的1、2月(即一年只有3~14月)。則每年仍然是單數月31天,雙數月爲30天,且歲首(M=3)仍爲大月,則僅需令上式再減1(2月少一天)。計算M月的積日,則有:int(30.5*M)-31(M>2)

該式只適用於M>2的情況,所以當爲1月或2月時,可令M=13、14,整式再減去一年365.25日,表現在年的積日公式中爲Y=Y-1。

一年的狀況(單數月31天,雙數月30天)

3月     4月    5月    6月    7月    8月    9月   10月  11月  12月   1月   2月

31天  30天  31天  30天  31天  30天  31天  30天  31天  30天  31天  30天-1

3. 對於公曆,又將8月增加一天成爲大月,以後9~12月則改變大小月順序,而二月再減去一日成爲28天。

一年的狀況(每5個月循環)

3月     4月    5月    6月    7月    8月    9月   10月  11月  12月   1月   2月

31天  30天  31天  30天  31天  31天  30天  31天  30天  31天  31天  30天-2

如此,7、8成爲連大月,12、13也是連大月。其中8月與歲首相差5月,13月與8月也相差5月。此時的大小月順序仍然存在某種規律,即每連續4月大小月相間(從小月開始),然後是一次連大月。即在一年12個月內,若以4月爲歲首,則大小月按小大小大大循環排序。亦即連續5月的積月爲153天(3大2小),平均每月爲30.6天。則M月的積日爲int(30.6*M)-31,由於該式是以3月爲歲首,需調整月份,即令M=M+1,再減去多算的一月30,並需減去2月再減少的1天則有:

int(30.6*(M+1))-62 

:由於儒略日的歷元是以正午12時開始(記爲0.0),而公曆一日之始以半夜12時開始(記爲1.0),兩種相差0.5天,則對日的積日爲實際日數-1.5

D - 1.5

將儒略曆轉換爲儒略日,僅需將年月日的積日相加,有:

int(365.25*(Y+4712))+int(30.6*(M+1))+D-63.5 (M>2)

當M<=2時:令Y = Y - 1,M = M + 12,可適用該公式

 

格里高利曆轉儒略日

:儒略曆合400年百閏。而在1582年發現春分點與實際相差10日(歲差22日,而儒略曆隨常較實際值爲大,多計算了12天。)故以是年10月4日的次日實行新曆(格里高利曆),曆元爲1582年10月15日。新曆在儒略曆的基礎上調整了歲差和迴歸年長度,即每400年減少3次置閏,合400年97閏。故計算格里高利曆的儒略日,還需在上式中減去不置閏(能被100整除,但不含能被400整除的年份)的日數,即爲-int((Y-1582)/100)+int((Y-1582)/400)-10,爲簡便算法,假設曆元爲0年,則自0年至1582年少算了不置閏的日數共12天,需加上,則計算格里曆的儒略日數需減去不置閏的日數:

-int(Y/100)+int(Y/400)+2

最終有格里高利曆轉儒略日的公式:

int(365.25*(Y+4712)) + int(30.6*(M+1)) + D - int(Y/100)+int(Y/400)+2 - 63.5  (M>2)

當M<=2時:令Y = Y - 1,M = M + 12,可適用該公式

補充說明:

(1)上式的int()函數表示向下取整,但在計算機中,int()函數一般僅取數字的整數部分,如int(-365.25)值爲-365而非366。考慮到當計算-4712年3月1日之前的數據時,Y=Y-1即-4713年,對年的積日運算中出現對負數取整的情況。故將曆元推到前一個置閏年爲-4716年以避免負數的取整運算,即多加了4年,需要在式尾中減去1460天。部分編程語言提供了向下取整函數,可用於替代上式的Int(),但調整曆元的方法更具有普適性。

(2)同樣考慮計算機對浮點數計算精度的問題,因爲計算機對十進制的表示和計算是以二進制進行的,無法得到精確值。故以30.6001替代30.6以避免出現計算誤差。

對此二者做出修正後,則有:

JDN = int(365.25*(Y+4716)) + int(30.6001*(M+1)) + D + B - 1524.5  (M>2)

當M<=2時:令Y = Y - 1,M = M + 12,可適用該公式

對儒略曆(公元前1582年10月4日及以前),有B = 0

對格里高利曆(公元前1582年10月15日及以後),有B = 2 - int(Y/100)+int(Y/400)

但對計算機而言,該式仍然不適用於計算-4716年3月1日前的儒略日數(但可以計算從儒略日起點開始的任意一天的儒略日數)。若使用向下取整函數替換int(),則該式可使用於任意一天的儒略日計算。

此式即可避免出現計算機取整運算與實際不一致的情況,從而避免因不同編程語言出現的計算誤差。

(3)wiki中提供了另一個公式,其實質與上式相同。[注3]

以3月爲歲首,每5個月符合大小大小大的順序,合計153天,平均每月30.6天。而計算起點爲大月,需加上0.4,取整後方得31。故有m月的積日爲int((153m+2)/5)。每年以365計,則需加上置閏年int(y/4)(365y+int(y/4)等價於int(365.25y))。式中將曆元前推到原曆元上一個符合置閏格里曆要求的年份-4800(公元前4801年)中午12時,則需在末尾減去(4800-4712)*365.25即32142天,還需再補上1月和2月合計59天,得32083日。對格里曆還需補上自-4712年至1582年少置閏的年份,共48天,減去上歲差和迴歸年過大引起的誤差共10天。

儒略日數的計算公式還有很多,但思路類似,不再舉例說明。

簡化儒略日

爲簡化儒略日的表示,國際天文聯合會決定行用簡化儒略日,並定義爲

MJD = JD -2400000.5

根據儒略日轉公曆的計算函數,可得MJD的的起點爲儒略日2400000.5,即公元1858年11月17日世界時0時。

儒略日計算的python實例

import datetime

def ce2jd(Y,M,D):
    if M in [1,2]:
        M += 12
        Y -= 1
    B = 0
    if Y>1582 or (Y==1582 and M>10) or (Y==1582 and M==10 and D>=15):
        B = 2 - int(Y/100) + int(Y/400)  #公元1582年10月15日以後每400年減少3閏
    JD = int(365.25*(Y+4712))+int(30.6*(M+1))+D+B-63.5
    print("{}年{}月{}日的儒略日爲:{:.1f}".format(Y,M,D,JD))
    if Y>1858 or (Y==1858 and M>11) or (Y==1858 and M==11 and D>=17):
        MJD = int(JD - 2400000.5)
        print("簡化儒略日爲:{}".format(MJD))

#示例:計算當前時間的儒略日
year = datetime.datetime.now().year
month = datetime.datetime.now().month
day = datetime.datetime.now().day
ce2jd(year,month,day)

 

儒略日轉公曆

def jd2ce(JDN):
    JDN  = JDN + 0.5
    Z = int(JDN)
    F  = JDN - Z
    if Z < 2299161: #格里曆
        A = Z
    else: #儒略曆
        a = int((Z - 1867216.25)/36524.25)
        A =  Z + 1 + a - int(a/4)
    B  = A +1524
    C = int((B-122.1)/365.25)
    D = int(365.25*C)
    E = int((B-D)/30.6001)
    day = B - D - int(30.6001*E) + F
    if E < 14:
        month = E - 1
    elif E < 16:
        month = E - 13
    if month > 2:
        year = C - 4716
    elif month in [1,2]:
        year = C - 4715
    print("儒略日{}對應的公曆日期爲{}年{}月{}日".format(JDN-0.5,year,month,day),'\n')

#計算示例
jd2ce(2400000.5)

注1:文中所用的“公曆”在公元前1582年10月4日適用儒略曆(雖然其曆元爲公元前45年1月1日半夜12時),在公元前1582年10月15日以後適用格里高利曆。

注2:出處Jean Meeus《Astronomical Algorithms》2nd。p59-66

注3:https://zh.wikipedia.org/wiki/%E5%84%92%E7%95%A5%E6%97%A5

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章