home · archive · links · projects

農曆的編算

公曆,也就是現行的格里高利曆,大多數人在小學的時候就學過,其規則也很簡單。但是農曆則不然,每一年春節似乎都在變動,和立春的日子根本不一樣,卻又總在它附近。而閏月更是讓人摸不着頭腦,每一個月都有可能稱爲閏月。

所以,這篇文章我就想寫一寫,農曆是怎樣編排出來的。

曆法的三個變量

世界上的歷法有很多種,大致可以分爲陰曆、陽曆、和陰陽曆。這些曆法所用的,無非就是三個變量:晝夜週期(天)、地球公轉週期(年)、月球盈虧週期(月)。注意,這裏說的是月球的盈虧週期而不是公轉週期。具體的原因後面再解釋。

不同的歷法會組合這三個變量。公曆是一種陽曆,選擇了"天"和"年",放棄了契合月球的盈虧週期。所以,公曆中的月僅僅具有象徵意義。伊斯蘭曆法是一種陰曆,契合了"天"和"月",而地球的公轉則完全不管了。所以,伊斯蘭曆法和地球公轉不匹配,伊斯蘭的一些節日,可能會出現在任何一個季節。中國的農曆選擇了最難的模式:陰陽曆。即,既要考慮月亮的盈虧,又要考慮地球的公轉。

如何劃定年

假如在地球上豎起一根杆子,記錄杆子在白天時影子的長度,那麼在中午十二點左右的某個時刻,影子會達到最短,這一刻就是正午。如果在溫帶,每天記錄正午的影子長度,就會發現,一年當中:冬天的某一天,正午影長是最長的;夏天的某一天,正午影長是最小的。

這就是"冬至"和"夏至"的定義。兩次冬至或者兩次夏至之間,就是一年了。雖然地球上的人類無法從太空中俯視地球的移動,但是用這麼一種簡單的方法,連續測量很多年,我們就可以知道地球公轉一週需要多少天。

中國古代的"圭表",就是用來測定影子的長度從而劃定"年"的。我們算出來的一年的長度,叫做"迴歸年"。

不過,這一切又沒有這麼簡單,地球的運動還有"歲差"和"章動"。而且,這也不是什麼新鮮的事物了,早在公元前二世紀就被古希臘天文學家所察覺。不過,對於本文來說,這些內容有些過於複雜了。

如何劃定二十四節氣

我們都知道有二十四節氣,在上一節只提到了冬至和夏至。接下來就是怎麼劃定剩下的二十二個了。

早年的方法是非常簡單粗暴的。既然冬至已經通過"迴歸年"計算出來了,那麼把兩次冬至之間的時間二十四等分成二十四個區間,也就有了二十四個節氣。

這種方法被稱爲"平氣法",其實很粗糙,就是簡單的除法運算,但是也夠用了。因爲地球的軌道是一個很近似圓的橢圓。所以地球的公轉速度大致還算比較均勻。

第二種方式更加的精密:定下夏至和冬至之後,按地球在公轉軌道上每轉過15度角記一個節氣。這種需要精確的天文觀測和數學計算,需要用到一些近代數學的內容。該方法叫做"定氣法",是在明末纔開始採用的,其中有外國的傳教士協助,是基於托勒密天文學制定的。根據開普勒定律我們能知道,地球的公轉軌道是橢圓,而且運轉的速度是不均勻的,所以節氣之間間隔的時間不完全一致。

二十四節氣中,從冬至或者夏至開始,第一、三、五、七……個節氣被稱爲"中氣",包括了夏至、大暑、處暑、秋分、霜降、小雪、冬至、大寒、雨水、春分、穀雨、小滿。你會發現,在公曆中,每個月固定會有兩個節氣,而月末的節氣就是"中氣"。這個定義在後面涉及閏月的時候會用到。

月亮週期

月亮的盈虧週期是29.5天,但是前面提到過,這並不是月球的公轉週期。月球的公轉週期是27.3天。月球在轉到地球背朝太陽的一側的時候達到滿月,也就是"望";在轉到面朝太陽的一面的時候就看不到月亮了,這就是"朔"。所謂"物極必反",完全看不到月亮的時間不會持續太久,很快,一絲月牙就會重新出現,所以"朔"這一天也會是新月出現的那一天。事實上,在天文學上,"月朔"和"新月"(英文:new moon)其實是同一個意思。本文當中也可能會交替使用這兩個詞。

當月球繞地球轉了一週的時候,地球也繞着太陽走了一點距離。所謂,月球要稍微多走一點路,才能達到相對太陽的相同位置。所以,月亮的盈虧週期會比公轉週期多一天。

根據農曆的定義,"朔"這一天就是每一個月的初一。又因爲盈虧的週期是29.5天,所以每一個農曆月的時間在29天到30天不等。

越南和我們同一天過年嗎?

越南也遵循傳統使用農曆,並且和中國基本相同。所以,農曆新年被稱爲"Chinese New Year"的時候,越南互聯網上還有一些反對的聲音,很多英文媒體也因此把農曆新年改作"Lunar New Year"。

不過,雖然使用的都是農曆,但是越南卻不一定和我們同一天過年。北京的時區在東八區,而越南的時區在東七區,有一個小時的時差。所以在特殊的情況下,相對北京時間,月朔會發生在午夜後,而相對河內時間,月朔會發生在午夜前。這樣,正月初一的時間就會錯開一天。因此,雖然我們和越南採用同樣的歷法,但是傳統新年的日期卻不一定相同。

"建子之月"、"建醜之月"、"建寅之月"

地支是以"子醜寅卯"開始的。如果你稍微瞭解一點生辰八字,就會發現,正月所對應的地支並不是"子",而是"寅"。而"子"所對應的月份是十一月。月份和地支的這種對應關係也被稱爲"月建"。據稱"建"是指北斗星所指的地方,十一月是"建子之月",北斗星指向"子"這個位置。

我非常不喜歡這個說法,它過於玄學了。"建子"有更明顯更深刻的含義,這也是農曆作爲陰陽曆的重大特點:農曆中規定,冬至必定位於"建子之月"。冬至這一天,剛好是一年中白晝最短、黑夜最長的一天。與之對應,十二時辰中的"子時"也是午夜。這種奇妙的遙相呼應,比用莫名奇妙的北斗七星定義要好多了。

春秋戰國時,把哪一個月份作爲正月是有爭議的。有的地方用建寅,有的地方用建醜,有的地方用建子。據稱,這三種正月分別是夏朝、殷朝、周朝的正月,稱爲"夏正"、"殷正"、"周正"。但是這種說法的真實性不可考證。秦朝又把"建亥",也就是冬至前的那個月份作爲一月。不過,在漢武帝年間,最終確定了"夏正",也就是把"建寅之月"作爲正月,"建子之月"也就相應地變成了十一月。

既然冬至在十一月,那麼冬至之後的第一個月朔,就是臘月初一,冬至後的第二個月朔,就是正月初一,也就是春節。

所以,如果有人問起春節究竟是怎麼確定的,你可以略帶神祕,用占星家的口吻說:"冬至後的第二個新月"。不過,這種說法又並不總是準確,因爲還有"閏月"。

置閏法

閏月是農曆中最複雜的部分。一個迴歸年大致是365.2422天,而一個朔望月是29.5天。如果一年記12個月,那麼就只有29.5 × 12 = 354天。差不多每隔兩三年就會和迴歸年偏差一個月。因此,當偏差發生時,就要增加額外一個月來補償。這就是閏月。

農曆的置閏法差不多分爲三個階段:

第一個階段是"十九年七閏"。在先秦使用的就是這種曆法。根據古人對朔望月週期和迴歸年的觀察,每隔19年差不多就有7個閏月。但是這種方法是非常粗糙的。

漢代以後,通行的置閏方法是"無中氣置閏"。前面提到了,二十四節氣中有十二個間隔分佈的"中氣"。如果使用二十四等分迴歸年的"平氣法",每兩個"中氣"之間間隔30.43天。隨着時間的推移,會出現有的月份沒有中氣,這時就置一個閏月。這個方法很好的兼顧了朔望月和迴歸年,計算也比較方便,因此一直施行到明末。

第三個階段,在明末的《崇禎曆書》和清初開始推行的《時憲曆》中,農曆進行了一次更大的升級,變成了今天的樣子。

現代的農曆

去讀《時憲曆》有點麻煩。所幸紫金山天文臺在2017年參與制定了一部農曆的國家標準《農曆的編算和頒行(GB/T 33661-2017)》,對於農曆如何置閏做了精確的描述。

這裏面除了第一條"北京時間"是古代所沒有的以外,其它都是和《時憲曆》一脈相承的。

和之前的歷法相比,《時憲曆》有兩個更新:第一個是制定節氣的方法變了,從"平氣法"變成了"定氣法",也就是說,從二十四等分一年來確定二十四節氣,變成了地球繞太陽每公轉15度爲一個節氣。定氣法需要非常精確的測量和複雜的計算,而明末的時候,中國的天文學已經落後於歐洲了,需要傳教士的幫助纔有可能實現。因爲地球是橢圓軌道,根據開普勒定律,不同季節的公轉速度不同,所以節氣間隔的天數變成了動態變化的14到16天。由此,置閏法也發生了變化,因爲月相週期時間相對穩定而節氣時間動態變化,所以無中氣的月份變多了,不能再簡單地用無中氣置閏法,否則閏月會過量;因此置閏法也修改成了兩個冬至之間含有13個農曆月的時候纔會加一個閏月。

從此,在農曆中,年、月、日完全由天文觀測確定:節氣完全由地球公轉確定,月份完全由月相週期確定,而年則是兩者相輔相成,加上置閏法之後計算得出。在現代儀器的幫助下,二十四節氣、朔望月、迴歸年的觀測都可以精確到秒乃至毫秒級別。反而是現行的公曆,因爲沒有根據天文觀測調整的機制,會和迴歸年逐漸發生誤差,幾千年就會偏差一日。

2033年問題

雖然《時憲曆》已經頒行了三百年,但是民間往往還因循守舊,使用古老的"無中氣置閏法"。在大多數年份,這兩者其實一樣,但是因爲種種細微的偏差,在2033年,"無中氣置閏法"和現代的農曆置閏法會發生衝突。2033年比較特殊,這個農曆年會有兩個無中氣的月份,分別是(原本的)八月和(原本的)十二月。如果按照"無中氣置閏法",那麼(原本的)八月就會變成七月的閏月,也就是閏七月,但是因爲從2032年農曆十一月開始到2033年農曆十一月之間只有12個農曆月,而2033年的農曆十一月到2034年的農曆十一月之間纔會有13個農曆月,所以閏月應該放在這一年的第二個無中氣的月份:十二月,讓十二月成爲閏十一月。而一些不採用現代置閏法的民間的"萬年曆"在這裏就可能會有錯誤,這會導致中秋節偏差了一個月。

同時,這也是爲什麼說農曆新年是"冬至之後的第二個新月"這樣的說法不準確,因爲如果出現了閏十一月或者閏臘月,那麼新年就會變成冬至之後的第三個新月。


© Licensed under CC BY-NC-SA 4.0 if not specified otherwise.
Email: dzshy [at] outlook [dot] com