漫談歷法、閏年與閏月

2/29

今年閏年,今天閏日,并且又趕上周末,寫一篇與技術(shù)不太相關(guān)的小文章吧。

回歸陽歷與閏年

由于地球的地軸與公轉(zhuǎn)軌道平面不垂直(即存在黃赤交角),因此在公轉(zhuǎn)的過程中,地球上的太陽直射點會周期性移動,即北半球夏至?xí)r陽光直射北回歸線,北半球冬至?xí)r陽光直射南回歸線,而春分、秋分時直射赤道,如下圖所示。

A~D即北半球春分、夏至、秋分、冬至

根據(jù)太陽直射點周期性移動制定的歷法稱為回歸陽歷(tropical solar calendar),一個周期的長度就稱為1回歸年(tropical year)。在2000年時測定的1回歸年長度為365天5小時48分45.19秒——即約365.2421897天。

回歸陽歷的代表就是格里歷(Gregorian calendar),即我們平時所說的“公歷”、“公元”。它由教皇額我略十三世(Gregory XIII)于1582年頒行,并首先在意大利、西班牙等地使用,進(jìn)而影響到全世界,1912年被中國采用。

格里歷(以及絕大多數(shù)回歸陽歷)的平年有365天,比回歸年少了1/4天不到。為了彌補(bǔ)人為歷法與實際回歸年之間的時間差,格里歷的制訂者規(guī)定每4年修正一次,即在大多數(shù)4的倍數(shù)年的2月加上一天——即2月29日,稱為閏日(leap day),對應(yīng)的那一年就是閏年(leap year)。

為什么是“大多數(shù)”4的倍數(shù)年,而不是“全部”?很顯然,如果以4個世紀(jì)為區(qū)間,所有4的倍數(shù)年都加上一天的話,那么這400年又會累積出大約3天的誤差。為了把這多出來的3天抹平,格里歷又規(guī)定在整世紀(jì)年中,只有400的倍數(shù)年為閏年(如1600、2000),其他的都是平年(如1700、1800、1900)。

所以,格里歷中正確判斷閏年的方法如下。

boolean isLeap(int year) {
  return (year % 4 == 0 && year % 100 != 0) || year % 400 == 0;
}

可以計算得知,格里歷的年平均長度為365 + ?1/4 ? ?1/100 + ?1/400 = 365.2425天,與回歸年的標(biāo)準(zhǔn)長度相當(dāng)接近,每約3300年才會又差出1天。至于這個誤差如何修正,就留給后人去解決吧。

下面這張圖表又示出了1800~2200年這四個世紀(jì)的時間中,由于閏年和閏日的影響,北半球夏至實際日期在公歷6月20、21、22日區(qū)間內(nèi)的波動。

公歷的閏年bug

閏年bug總體上講沒有千年蟲那么嚴(yán)重,但是也會造成困擾。比如2012年時,微軟的Azure服務(wù)因為閏年bug導(dǎo)致整體下線(詳情請見這里),而于此同時,谷歌的Gmail聊天歷史中也因為閏年bug將所有2月29日的記錄標(biāo)成了1969年12月31日。直到今天,Excel仍然會錯誤地認(rèn)為1900年是個閏年(輸入1900年2月29日,會被Excel認(rèn)為是合法的),這個問題很久遠(yuǎn)了,詳情可以參見這里

在程序設(shè)計語言中做基于年的運算,也會出現(xiàn)小型的閏年bug,例如C#:

DateTime dt = DateTime.Now;
DateTime result = new DateTime(dt.Year + 1, dt.Month, dt.Day);

在今天執(zhí)行這條語句,會直接拋出ArgumentOutOfRangeException,因為2021年是平年,沒有2月29日。

又例如JS:

var dt = new Date();
dt.setFullYear(dt.getFullYear() + 1);

dt的值會變成2021年3月1日,因為JS檢測到2021年2月29日不存在,就會自動置入下一個有效的日期。但是,如果以正常的一年365天計,結(jié)果應(yīng)該是2021年2月28日才正確。

恒星陽歷

與回歸陽歷相對的陽歷歷法是恒星陽歷(sidereal solar calendar),顧名思義,它是以太陽、地球與某一恒星的相對位置來確定的歷法。從地球上看,太陽從黃道上與某恒星共線的位置出發(fā),再次回到與該恒星共線的位置的周期即為1恒星年(sidereal year)。1恒星年也就是地球?qū)嶋H上的公轉(zhuǎn)周期,計365天6小時9分9.76秒——即約365.256363004天。

采用恒星陽歷的歷法不多,主要分布在南亞次大陸,如印度歷。由于相同的誤差原因,恒星陽歷也會有閏年,不再多講。

陰陽歷與閏月

陰陽歷(lunisolar calendar)是另一種主流的歷法。陰陽歷中的一年以地球公轉(zhuǎn)周期——即回歸年或恒星年來定義,但是月份和日期以月球公轉(zhuǎn)周期——即朔望月來定義。陰陽歷法在東亞地區(qū)有很悠久的歷史,最具代表性的就是中國農(nóng)歷,日本、韓國、越南等國現(xiàn)今也仍然采用中國農(nóng)歷與其變種。

需要注意,雖然民間經(jīng)常將農(nóng)歷叫做“陰歷”,但嚴(yán)格來講它是陰陽歷。真正的“陰歷”是不考慮地球公轉(zhuǎn)周期的,如伊斯蘭歷,就不贅述了。

中國農(nóng)歷的“陽”,體現(xiàn)在二十四節(jié)氣。古人根據(jù)太陽的視運動與自然氣象的變化,將太陽沿黃經(jīng)每運行15度所經(jīng)歷的時日稱為一個節(jié)氣,以指導(dǎo)農(nóng)業(yè)生產(chǎn)。太陽運行360度為1回歸年,正好是24個節(jié)氣。所以二十四節(jié)氣恰好能平分給公歷的12個月份,并且日期也比較固定,上半年在6日、21日左右,下半年在8日、23日左右,正如《新華字典》附錄的節(jié)氣歌所述:

春雨驚春清谷天,夏滿芒夏暑相連。
秋處露秋寒霜降,冬雪雪冬小大寒。
每月兩節(jié)不變更,最多相差一兩天。
上半年來六廿一,下半年是八廿三。

中國農(nóng)歷的“陰”,則體現(xiàn)在以月相定義月份。具體來說,是以月球合朔(即月亮陰面朝向地球)發(fā)生的那一天為該月的初一日,月圓(即“望”)的那一天則是十五日。月球兩次合朔經(jīng)過的周期就是朔望月,即農(nóng)歷的一個月。

由于攝動的因素,朔望月的長度大約在29.27至29.83天之間變動,而長時期的平均長度大約為29.530588天(29天12小時44分2.8秒)。所以農(nóng)歷中會有大小月之分,大月30日,小月29日,嚴(yán)格按照天文觀測來確定——這點與公歷不同,公歷每個月的天數(shù)完全是人為規(guī)定的。

一個農(nóng)歷年的平年由12個月組成,即大約29.5 * 12 = 354日,但一個回歸年大約是365又1/4日,差了大約11天。這個誤差是比較大的,積累十幾年就會出現(xiàn)月份與季節(jié)氣候完全對不上的情況,所以古人才發(fā)明了“閏月”,以協(xié)調(diào)回歸年與農(nóng)歷年。

那么什么時候需要插入閏月呢?決定閏月的算法稱為“無中置閏法”,早在《太初歷》(公元前104年)就已經(jīng)有了。《后漢書·律歷下》有言:

...故置十二中以定月位。有朔而無中者為閏月。中之始曰節(jié),與中為二十四氣。

該算法確立了一個大前提,即農(nóng)歷年起于冬至,終于冬至(所以冬至也是一個重要的節(jié)日),這樣就把回歸年和農(nóng)歷年的長度統(tǒng)一起來了。

接下來,檢查一年中兩個冬至之間有幾個朔望月。如果有12個,說明是正常的,不需要加閏月。如果有13個,那么就從農(nóng)歷二月到十月間,將第一個沒有“中氣”的月定為閏月,這個月跟在哪個正常的月份后面就是閏幾月。所謂中氣,其實就是指太陽運行到30度角倍數(shù)的12個節(jié)氣,即雨水、春分、谷雨、小滿、夏至、大暑、處暑、秋分、霜降、小雪、冬至、大寒。

為什么會有月份沒有中氣?因為地球的軌道并不是圓的,而是近似橢圓,所以在遠(yuǎn)日點附近(北半球夏季左右)公轉(zhuǎn)較慢,導(dǎo)致兩個中氣之間的間隔(平均約30.43日,最長可達(dá)31.45日)被拉長,長于朔望月的長度,所以會有月份恰好卡在了兩個中氣之間。舉個例子,2001年5月21日(四月二十九)是小滿節(jié)氣,下一個朔望月的區(qū)間是5月23日到6月20日,但下一個中氣——即夏至——卻是6月21日。所以這個朔望月沒有中氣,從5月23日起即為閏四月初一,直到6月20日為閏四月廿九,從6月21日才算五月。

The End

從沒寫過這樣的東西,有點意思。

民那晚安。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,797評論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,179評論 3 414
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,628評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,642評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 71,444評論 6 405
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 54,948評論 1 321
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,040評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,185評論 0 287
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,717評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 40,602評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,794評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,316評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,045評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,418評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,671評論 1 281
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,414評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 47,750評論 2 370