返回农历编算法则


农 历 法 则 之 疑 惑

初稿: 2018年10月       最近一次重大修订: 2019年4月



看了农历的编算法则后,也许读者会感到疑惑:为什么要这样编制农历?


兼 顾 阴 阳 两 周

阴阳历的重点是既要考虑月亮盈亏周期(朔望月),也要照顾季节交替周期(回归年)。法则三显然是为了照顾月相。把朔日定为初一,保证初一看不见月亮,农历月的各日也大致有相同的月相,例如望(满月)发生在每月的十六日左右。法则四和法则五则是为了使农历月份不偏离季节。把冬至定在十一月,保证十一月是冬天,因此十一月又称「冬月」。但是冬至与月相无关,某年的冬至可以发生在朔日,另一年却可以发生在朔日前一天(又称「晦日」)。结合法则三,可推断冬至可以在十一月初一,也可以在十一月最后一日。所以冬至在农历有三十天的浮动,而在公历只有三天浮动。

顺治二年(1645年)历法改革前,农历的月份与中气有一一对应关系,例如正月必含雨水,二月必含春分等。顺治历改后,这样的对应关系仍然在大多数时候成立,但会有少数例外,这点在二十四节气网页有详细说明。然而即使在那些少数例外里,中气也只是偏离了对应月份仅仅一天而已,因此可以说所有中气在农历有约三十天的浮动。所有二十四节气在公历里只有三天浮动,比农历小得多,这是农历要兼顾阴阳两周的代价。


十 九 年 七 闰 法 之 谜

中国在春秋战国时已发现235(=19×12+7)个朔望月与19个回归年的时间非常接近,于是采用十九年七闰法编制农历,即在十九个农历年里放置七个闰月。古时称十九为章岁,七为章闰。后人把章岁和章闰合称为闰周。

有不少书籍和文章说农历用十九年七闰法来兼顾阴阳两周,谈到如何在十九年里加七个闰月时就说以无中气的月份定为闰月。或许读者会感到疑惑:以无中气定闰月为什么能保证在十九年里置七个闰月?答案是「不能保证」!首先,「无中气」置闰法在顺治历改后已废除,在现行置闰法则下,无中气的月份虽然大多数确是闰月,但有少数例外。再则十九年七闰法其实在南北朝末期到隋唐间基本上已废除,原因是19个回归年比235个朔望月短约二小时,用十九年七闰法制定的历法(例如犹太历)在228年会有一日偏差。

战国至魏晋期间中国的历法确是采用十九年七闰法,自汉武帝太初元年(公元前104年)起开始采用无中气法设置闰月。唐朝以前的历法用平朔法计算合朔,即假设月亮和太阳在天空运行速度是均匀的,两合朔之间的时间间隔是常数。南北朝以前的历法一般采用的回归年与朔望月的比例是235:19,所以19岁正好有235个月。每岁有12个中气,19岁就有228个中气,235=228+7,所以有七个月不含中气,因此以无中气法置闰能保证十九年有七个闰月。

后来因观测精度提高,发现十九年七闰法稍嫌粗糙,于是废弃了回归年:朔望月=235:19的比例。例如南北朝时期祖冲之创制的《大明历》实行三百九十一年一百四十四闰,具体做法是取回归年:朔望月=4836:391,4836 = 391×12 + 144,用无中气法置闰得391年144闰。这称之为「破章法」,即打破章闰之法,第一部采用破章法的历法是《玄始历》(600年221闰),由北凉国太史著,在北涼行用了28年,在北魏行用了71年。到了唐朝,合朔计算改用定朔,两合朔的时间间隔不再是常数,到了清朝,连二十四节气也改用定气法计算,两中气的时间间隔也不再是常数,无中气法也要修改成现行的置闰法,这样更不能保证十九年有七个闰月。

虽然闰周只是近似周期,细看按现时置闰法则的闰月分布,不难发现闰月规律大致符合十九年周期。下表列出从农历N1930到N2500几百年间的闰月,分三十行每行七栏排列,每行代表一个闰周的闰月。如前述,法则一在1929年才实施,所以表列的年份从1930年起,以确保所列的闰月都是按相同法则而定。

闰周农历年: 闰月
1N1930: 六N1933: 五N1936: 三N1938: 七N1941: 六N1944: 四N1947: 二
2N1949: 七N1952: 五N1955: 三N1957: 八N1960: 六N1963: 四N1966: 三
3N1968: 七N1971: 五N1974: 四N1976: 八N1979: 六N1982: 四N1984: 十
4N1987: 六N1990: 五N1993: 三N1995: 八N1998: 五N2001: 四N2004: 二
5N2006: 七N2009: 五N2012: 四N2014: 九N2017: 六N2020: 四N2023: 二
6N2025: 六N2028: 五N2031: 三N2033: 十一N2036: 六N2039: 五N2042: 二
7N2044: 七N2047: 五N2050: 三N2052: 八N2055: 六N2058: 四N2061: 三
8N2063: 七N2066: 五N2069: 四N2071: 八N2074: 六N2077: 四N2080: 三
9N2082: 七N2085: 五N2088: 四N2090: 八N2093: 六N2096: 四N2099: 二
10N2101: 七N2104: 五N2107: 四N2109: 九N2112: 六N2115: 四N2118: 三
11N2120: 七N2123: 五N2126: 四N2128: 十一N2131: 六N2134: 五N2137: 二
12N2139: 七N2142: 五N2145: 四N2147: 十一N2150: 六N2153: 五N2156: 三
13N2158: 七N2161: 六N2164: 四N2166: 十N2169: 六N2172: 五N2175: 三
14N2177: 七N2180: 六N2183: 四N2186: 二N2188: 六N2191: 五N2194: 三
15N2196: 七N2199: 六N2202: 四N2204: 九N2207: 六N2210: 四N2213: 三
16N2215: 七N2218: 五N2221: 四N2223: 九N2226: 七N2229: 五N2232: 三
17N2234: 八N2237: 五N2240: 四N2242: 十一N2245: 六N2248: 五N2251: 三
18N2253: 七N2256: 六N2259: 五N2262: 正N2264: 七N2267: 五N2270: 三
19N2272: 八N2275: 六N2278: 四N2281: 二N2283: 六N2286: 五N2289: 三
20N2291: 七N2294: 六N2297: 四N2300: 二N2302: 六N2305: 五N2308: 三
21N2310: 七N2313: 六N2316: 四N2318: 十N2321: 七N2324: 五N2327: 三
22N2329: 八N2332: 六N2335: 四N2338: 三N2340: 七N2343: 五N2346: 四
23N2348: 八N2351: 六N2354: 五N2357: 正N2359: 七N2362: 五N2365: 四
24N2367: 八N2370: 六N2373: 五N2376: 二N2378: 七N2381: 五N2384: 四
25N2386: 十N2389: 六N2392: 四N2395: 二N2397: 六N2400: 五N2403: 三
26N2405: 八N2408: 六N2411: 五N2414: 二N2416: 七N2419: 五N2422: 三
27N2424: 八N2427: 六N2430: 四N2433: 三N2435: 七N2438: 五N2441: 四
28N2443: 八N2446: 七N2449: 五N2452: 三N2454: 八N2457: 五N2460: 四
29N2462: 八N2465: 六N2468: 五N2471: 三N2473: 七N2476: 五N2479: 四
30N2481: 十N2484: 六N2487: 五N2490: 三N2492: 七N2495: 五N2498: 四

从表中可见闰月确是大致符合十九年周期,例如每一栏的年份确是大多数相差十九年,但有若干例外。粉红色的方格表示闰月的年份偏离了十九年的规律,例如第三闰周的最后一个闰月早了几个月出现。每一栏的闰月也大致上闰同一个月,但也有例外。黄色方格表示闰月出现的月份「错了」,意思是说闰月的月份与其在此栏的其他闰月有颇大偏差。例如在第六闰周里,N2033的闰月出现在闰十一月,而该栏的其他闰月一般是闰七月、闰八月或闰九月。有趣的是第四栏的闰月在第十七闰周前一般是闰七月、闰八月或闰九月,出见了一连串「错误」的闰月后,索性「错到底」,到了第十七闰周以后改为闰正月、闰二月或闰三月。这些偏离闰周的「异常情况」显示了闰周只是闰月的近似周期,要使农历不偏离阴阳两周,在几百年内需要有若干闰月打破闰周的规律。

从表中可见自1930年后闰正月会首次出现在N2262,其实这是自顺治历改(1645年)后首次出现的闰正月,这点在前新加波国立大学数学系教授Helmer Aslaksen(现任挪威奥斯陆大学副教授)撰写的中国历法中的数学一文中指出,我的独立计算与他的结果相符。

最后要指出目前不能很准确计算几百年后的朔和二十四节气的UTC+8时刻,这是因为地球自转不均匀,以致难以准确预测几百年后会有多少闰秒加到UTC上。公元2200年后的时间计算或会有几分钟误差,如果朔或节气时间发生在离午夜零时几分钟之内,朔日和节气日期或会有一日偏差,这一日之差一般不会影响闰月的编排,但在少数的情况下或会改变闰月,所以上表列出的数据可能有一两个会有错,但不会影响闰月的整体分布。


农 历 年 月 的 平 均 日 数

乍看农历编算的法则,似乎不易从中推出农历年和农历月的平均周期。其实要估计农历年月的平均日数不难:农历月的平均长度应接近朔望月的平均值29.530589日,而农历年的平均长度应接近回归年365.2422日。这估计是用反证法而得。假设农历月的平均长度与朔望月的平均值有颇大偏差,则朔的平均时刻在农历月里会渐渐漂移,最终会漂离初一日,但这与法则三相悖,所以原先的假设不成立。同理,假设农历年的平均值颇大地偏离回归年,则冬至的平均时刻在农历十一月会渐渐漂移,最终会漂离十一月,但这与法则四相悖,所以原先的假设不成立。这样的论述只是估算而不是严格证明,其一是因为平均值的运算没有准确界定,其二是朔望月平均值和回归年都随时间而变。

这里再展示好一点的计算。用FY+k(k是整数)表示农历年NY+k正月初一UTC正午的儒略日数(所以FY+k是整数);用WY+k表示在公历Y+k年冬至时刻的儒略日数(所以WY+k一般不是整数);设定ΔFY+k=FY+k - WY+k-1,是从Y+k-1年的冬至到农历年NY+k正月初一UTC正午的日数。农历年从NYNY+n这n年的平均日数是

Y = (FY+n+1 - FY) / n = (WY+n - WY-1) / n + (ΔFY+n+1 - ΔFY) / n

(WY+n - WY-1) / n 是两冬至在Y-1到Y+n年间的平均日数,这个平均值接近回归年。正月初一是在冬至后的第二或第三个朔日,所以|ΔFY+n+1 - ΔFY|必定少于某常数U。已知正月初一在公历的1月20日和2月20日之间浮动,冬至在公历12月21日到12月23日左右浮动,所以U应接近30日。U的确实数字不重要,重要的是U是有限的。所以当n增加,|ΔFY+n+1 - ΔFY| / n 就会越来越少,从而推出农历年的平均日数接近回归年。用类似的方法可以得出农历月的平均日数接近朔望月。

现在来看看实际数据。据我的计算,从N1929到N2200这272农历年间有99340日,所以农历年在这272年的平均日数是99340/272=365.22日,比回归年短约半小时。然而农历年长度年年不同,其日数在353日与385日之间,标准偏差是14.31日。意味着平均值会随所取平均的年份而有所变化。例如农历年在N1929到N2199这271年间的平均日数是365.262日,在N1929到N2198这270年间的平均日数是365.1926日,这些变动主要来自(ΔF1930+n - ΔF1929)/n这项随着n变化而产生的变动,这变化会随取平均的年数增加而降底至零。下图显示农历年在N1929NY的平均日数随着Y由2150到2200的变化。

Average length of a Chinese year

可见农历年的平均值在365.16日到365.28日之间变动,这就是取270农历年左右的平均值的结果,要减少平均值的变化,可取更多农历年的平均值。下图显示农历年在N1929NY的平均日数随着Y由2878到2928的变化。取平均值的农历年数高达一千。

Average length of a Chinese year

图中可见农历年数目增加到一千左右时,其平均日数在365.224日与365.255日之间变动,变化幅度小了约四倍。这正与预期的一致,因为变动幅度应与n成反比,此处n是取平均的年数。农历年的平均日数确是接近回归年365.242日。

现在再看农历月的平均日数,从N1929N2200这272农历年间有3364个农历月(包括闰月),前面说过这272农历年有99340日,所以农历月在这3364个月的平均日数是99340/3364=29.5303日。为了知道这个平均值随月数的变化,下图显示农历月在N1930起算的第一个月到第M个月的平均值随着M由3300到3364的变化。

Average length of a Chinese year

图中可见农历月平均值的变化远少于农历年的平均值变化,这是由两个因数造成。其一是农历每月的日数变化只有一日(二十九日或三十日),其二是现在在取几千个数的平均值,而不是几百个数的平均值。农历月在这三千几个月的平均日数在29.5300日和29.5306日之间变动,确是接近朔望月的平均值29.530589日。



返回农历编算法则