Chen Yangjian's Blog

Carpe diem - Seize the day

农历、格里历以及转换

| Comments

前些天练手 django,做了个袁天罡称骨歌小工具,在阳历与农历转换之间犯了难,后来让用户直接输农历了事,原先的 jQuery date_input 插件,也就不好再用。

这让我很郁闷,于是找了个 python 阳历农历转换之类的代码,该程序老旧,然而记录的150年农历倒是实用的,于是拿来主义,取将过来,写了个简单的阳历、农历互相转换程序,测试不多,或将挂到网上。

二者之间的转换比预想的很不一样,现行的国际通用的公历,又叫格里历(Gregorian Calendar),是 Julian Calendar的改进版。1582 年的时候,教宗 Gregory 十三,为了矫正凯撒(Julius Caesar)改自罗马历法的 Julian Calendar 长期使用起来与实际时间产生的偏差(根据《The Mathematics of Chinese Calendar》):

The reason why the Catholic church had to reform the Julian calendar was because the rules for computing Easter had fixed the March equinox to be March 21. That meant that Easter was drifting noticeably towards summer.

重置了日期的时间,并调整了闰年的算法。

The last day of the Julian calendar was Thursday, 4 October 1582 and this was followed by the first day of the Gregorian calendar, Friday, 15 October 1582 (the cycle of weekdays was not affected).

Every year that is exactly divisible by four is a leap year, except for years that are exactly divisible by 100; the centurial years that are exactly divisible by 400 are still leap years. For example, the year 1900 is not a leap year; the year 2000 is a leap year.

原先的历法中,木有能被100整除并且不能被400整除不是闰年这一条。

同时,值得八卦的是,在凯撒修改之前的罗马历法中,October 还是正宗的 October,指的是一年中的第八个月,这与英文 octal 八进制还是对应的。

格里历是个计算性的历法,一年十二个月,大小月(31、30天)固定,2月分作为特殊月份,普通年份28天,闰年29天,用以调整历法与实际的偏差,365.2425 天。

而农历呢?农历又叫阴历、古历,是一个沿用数千年,历经无数次合理的不合理不得已的不想要的让人欢喜的让人抓狂的修改增编之后的历法。它最近的一次修改实在 1645 年,明朝朱棣皇帝迁都北京(1403年)两百多年之后。明朝时,皇家看星星团(钦天监)的职位变为世袭,仰望星空的文武百官早已不再理解祖宗历法,从南京到北京,经纬度变化,使得原先预演月球阴晴的遗产算式不再能被套用,这帮食君俸禄的家伙连怎么调整浑天仪都不知道。然后,1582年,利玛窦同学本着上帝的名义来到中国,策反了时任当朝大员徐光启,中国人终于开始领受洋人的思想。而后,明朝覆亡(1644年),东北的少数民族爱新觉罗们,踩着徐光启和利玛窦们的肩膀,根据引进的洋人的新式天文设备,在又一个传教士汤若望、罗雅谷的主持下,将他们的历局并入钦天监接着修订历法。然而新历出笼之后,保守佞臣杨光先,伙同什么都想插一脚的鳌拜,认为“宁可使 中国无好历法,不可使中国有西洋人”,收押了汤若望以及南怀仁。

插播八卦,汤若望在顺治即位之后,学会了一级甲等的普通话,尝试想让顺治信基督耶稣;顺治对此颇感兴趣,然而在汤若望说到婚姻,天主教徒一夫一妻制的时候,他的兴趣便也索然,转而去跟得道高僧们谈经了。

1665年1月16日,在汤与南仍在收押时,有一次日食,钦天监的三派,遵阴阳历的杨光先、奉阴历的穆斯林吴明烜和受哥白尼、伽利略等影响的汤若望南怀仁分别预测为当天下午2:30、2:15、3:00。一同收押的数名旅华外籍人士以及他们的中国助手们,戴着铁链镣铐,与当天下午2:57,见证了自己的信仰。然而,要面子如扬光先、鳌拜,是不需反悔的。汤若望与南怀仁的死刑被无限延缓,然而他们的中国助手们,被认为里通外人,处以极刑。1666年,汤在监禁中去世。

许多年后,我们称之为皇历的东西,其实跟洋人们不无关系。祖宗历法,并不比西洋历法低劣;郭守敬(受穆斯林历法的影响,修《授时历》,为当时世界上最准确的历法)比任何传教徒都胜任天文学家之职。然而,保守的中国人们,最终忘记了算法的本质。

以上,只是中国历法漫漫数千年间的一小部分。详细请参考《The Mathematics of Chinese Calendar》和维基百科-农历历代历法。上述历史,亦是译自该文。

再说回到转换,先插播点基础知识。所谓阳历、阴历、阴阳历,区别在于,阳历的历法基准,以太阳的变化、地球围绕太阳的周转为根据;阴历,则以月亮的阴晴圆缺为依托;而所谓阴阳历呢,则是二者在历法中都有其成分。农历本身,并不像格里历那样是个以数学计算为出发点的日历,以阴历为基本,插入阳历性质的二十四节气。这也是由中国农耕社会性质决定的。

月亮就跟齐秦的心一样,是阴晴不定的,循环周期也受太阳、其他行星等影响,所以,没有普通算法能够胜任。所能依据的,只能是航天局、天朝看星星团之类的机构公布的数据。开篇我提到有个 python 程序,里头含有1900-2050年的农历数据,如下:

                        0x04bd8,    # 1900
    0x04ae0, 0x0a570, 0x054d5, 0x0d260, 0x0d950,    # 1905
    ...
    0x0aa50, 0x1b255, 0x06d20, 0x0ada0          # 2049

编码的方式是:

# 0x0   c   a   b   5
#   0   1100    1010    1011    5 is the intercalary month

全部数据,去参考程序就好了。

Comments