快捷搜索:

科学知识

当前位置:betway必威官网手机版 > 科学知识 > 算法系列之二十,是为了庆祝日月合璧

算法系列之二十,是为了庆祝日月合璧

来源:http://www.abirdfarm.com 作者:betway必威官网手机版 时间:2019-08-22 23:55

又到了一年中我们最看重的节日,也是最增加体重的节日。一到这个时节,我们计算日期的方式就会自动从公历切换成我们传统历法——夏历。二十三过小年(有的地方是过二十四),到除夕,再到正月十五,一直等到这个春节过完,开始上班,再切换回公历日期。

        世界各国的日历都是以天为最小单位,但是关于年和月的算法却各不相同,大致可以分为三类:

很多朋友都不知道农历、阴历是怎么一回事,尤其是城市里的小孩,压根就没听说过农历这一说法。比如我们过年过中秋节等都是按照农历算的。

(接上篇)

以除夕夜半为标志,之前是丁酉鸡年,之后是戊戌狗年。除夕之夜,许多地方有守岁的风俗,这个习惯也由来已久。晋代大名士周处《风土记》:“蜀之风俗,晚岁相与馈问,谓之馈岁;酒食相邀为别岁;至除夕达旦不眠,谓之守岁。”这个周处就是我们课本上学过“周处除三害”的那个周处,上山打虎,入水杀蛟,然后从不良少年变成了学霸(别人家的孩子!)。馈岁是送礼,别岁是吃吃喝喝,守岁是通宵不睡,看来传统习俗的力量真是强大,至今我们还是这样过年的。

 

通常所说的阴历也叫农历、夏历。是中国的一种历法,是阴阳历的一种,一般叫作阴历。平年十二个月,大月三十天,小月二十九天,全年354天或355天。由于每年的天数比太阳年约差十一天,所以在十九年里设置七个闰月,有闰月的年份全年383天或384天。又根据太阳的位置,把一个太阳年分成二十四个节气,以利于农业种植等活动。纪年用天干地支搭配,六十年周而复始。这种历法相传创始于夏代,所以又称为夏历。也叫旧历。

        所谓的“天文算法”,就是利用经典力学定律推导行星运转轨道,对任意时刻的行星位置进行精确计算,从而获得某种天文现象发生时的时间,比如日月合朔这一天文现象就是太阳和月亮的地心黄经(视黄经)差为0的那一瞬间。能够计算任意时刻行星位置的一套理论就被称为星历表,比较著名的星历表有美国国家航空航天局下属的喷气推进实验室发布的DE系列星历表,还有瑞士天文台在DE406基础上拓展的瑞士星历表等等。根据行星运行轨道直接计算行星位置通常不是很方便,更何况大多数民用天文计算用不上那么多精确的轨道参数,于是天文学家在这些星历表的基础上推导出了很多可以做简便计算,但是又能保证一定精度的行星运行理论,比较著名的有VSOP82/87太阳系行星运行理论和ELP-2000/82月球运行理论,这两套理论在精度上已经很接近DE系列星历表了。关于如何应用这两套伦理进行天文历法计算,请参考“日历生成算法”系列文章的第三篇《用天文方法计算二十四节气》和第四篇《用天文方法计算日月合朔》,本文介绍的农历年历推算是在已经通过天文算法获得了精确的节气时间和日月合朔时间的基础上进行的。

不过,夏历毕竟是“旧历”了,我们有必要重新,也从新,来理解一下“过年”的这个传统。毕竟,随着许多传统习俗渐行渐远,我们对它既熟悉又陌生了。比如,习惯上我们会把夏历称为阴历,这虽然并不准确,倒也有道理可说,因为我们夏历计算月份和日期,就是按照太阴即月亮的运行来数的。

阳历--以天文年作为日历的主要周期,例如:中国公历(格里历)

公历称为“阳历”,民间的传统的“夏历”、“农历”通俗地称之为“阴历”。

        中国的官方纪时采用的是中国公历(格里历),因此农历年历的推导应以公历年的周期为主导,附上农历年的信息,也就是说,年历以公历的1月1日为起始,至12月31日结束,根据农历历法推导出的农历日期信息,附加在公历日期信息上形成双历。通常情况下,一个公历年周期都不能完整地对应到一个农历年周期上,二者的偏差也不固定,因此不存在稳定的对应关系,也就是说,不存在从公历的日期到农历日期的转换公式,只能根据农历的历法规则推导出农历日期与公历日期的对应关系。由农历历法规则可知,上一个公历年的冬至()所在的朔望月是上一个农历年的十一月(冬月),所以在进行节气计算时,需要计算包括上一年冬至节气在内的二十五个节气,才能对应上上一个农历年的十一月和当前农历年的十一月。在计算与之对应的朔日时,考虑到有闰月的情况,需要从上一年冬至节气前的第一个朔日,连续计算15个朔日才能保证覆盖两个冬至之间的一整年时间,图(1)显示了2011年没有闰月的情况下朔日和冬至的关系:

月亮的日子和月子

我经常会提问(给大家挖个坑):“一个月有多少天?”。很多人不假思索地回答,“28、29、30、31天都有可能”。恭喜这些朋友,对公历掌握得很好,连闰年2月有29天都记得。如果我们翻一下我们日历上的夏历日期,你会发现夏历一个月只有两种情况,29天或30天。

图片 1图片来源:rawpixel.com | Unsplash

我们的时间历法都来自日月运行,尤其是中国传统历法夏历一直使用朔望月,也就是日期遵循月相的变化——月相变化一周期就是一个朔望月。古人观天象,看起来月亮走到太阳的旁边,离得最近(当然此时我们是看不见月亮的,除非发生日食才能看见“黑月亮”),这个时候就叫,称为日月合朔。朔就是夏历的初一。过大约十五天之后,月亮会走到另一边,变成一轮圆月,跟太阳遥遥相望,这个时候就叫,称为日月相望,望就是夏历十五左右。

在我们日历上,还会写着“腊月大”“正月小”。比如今天这个腊月有30天,就是“腊月大”,我们可以过大年三十;而明天的正月只有29天,就是“正月小”。在有些年份,腊月是小月,大年二十九就是除夕过年了。

每个朔望月的月相变化,朔日为初一,然后是月芽(初二或初三)、上弦月(初七八,半个月亮)、月望(满月)、下弦月(二十二三,又是半个月亮),每个月最后一天称为。《庄子·逍遥游》说“朝菌不知晦朔”,就是说有些东西寿命还不到一天,你不能指望它懂得一个月的事儿。

图片 2月相变化示意图,图源:Guokr

使用朔望月的好处是,夜晚有月亮这个天然指示物告诉还没有手表更没有手机的古代人们,今天是几号,别错过了约会。所见即所得,这种直观对于古人来说显然是很重要的。即使现代公历(起源于古埃及和罗马帝国)里的“月份”虽然已经不再跟月相发生联系,但无论名字(month),还是长度(大约30天),还是个数(12个月),都还带着月亮的痕迹。

阴历--以天文月作为日历的主要周期,例如:伊斯兰历

阳历是以地球环绕太阳一周的时间算作一年。它的长度为三百六十五天五小时四十八分四十六秒。由于它不是整数,为了把长短拉平,有的年份是三百六十六天,称为“闰年”;有的年份是三百六十五天,称为“平年”。

图片 3

初一日月合璧

初生的月芽,俗称新月,也叫蛾眉月。其实“朔”的字形就告诉我们,它的本意是像初生的小草一样的小月芽。《西京杂记》说,“月之旦为朔”。“可怜九月初三夜,露似珍珠月似弓”,每月的月初,太阳从地平线沉下去之后,在西方低空可以看到的那一弯新月,赢得了全世界人们的喜爱。它标志着经历了几天看不见月亮的日子之后,月亮又重新回到了天空,照亮夜晚回家的路。

当然,最初各民族都曾把能够看到这一弯新月的日子作为一个月的开始。这个习俗至今仍保留在伊斯兰教历、希伯来历、印度历和佛历中。这样的历法中要确认在当地能够看到新月出现才开始新的一个月。

新月又叫“蛾眉月”,注意是“蛾”,而不是“娥”更不是“峨”,因为这里“蛾眉”指的是古人常见的蚕蛾细长的触须状。唐代有“蛾眉妆”,女子把眉毛画成蚕蛾触须的样子,可见蚕桑文化对中国文化的影响。唐人有诗描写这种蛾眉妆的流行:

    京兆眉(唐·刘方平)

    新作蛾眉样,

    谁将月里同。

    有来凡几日,

    相效满城中。

不过在我们祖先把朔日初一规定为“日月合朔”之后,在天文术语里,“朔”和“新月”的含义,就从看得见的月芽,变成了看不见的那个时刻的月亮。从准确性上来说,这样的规定显然要更为合适,因为月芽的可见性因地点而异,因天气而异,还因人而异。

日月合朔,又称“日月合璧”,它的重要性,还跟古人对宇宙的认识有关。古代帝王自称天子,老天爷的儿子,那么天文历法理所当然就是皇家的特权,俗称“皇历”,或者,“黄历”。黄历颁行天下,必须要计算准确。《汉书.律历志上》记载,“宦者淳于陵渠复覆《太初历》晦朔弦望,皆最密,日月如合璧,五星如连珠。”就是说,《太初历》对月相变化、日月五星的运行计算得都非常准确,应该采用。“日月如合璧,五星如连珠”这是古人所看重的天上“祥瑞”,这个表述在春秋战国时写成的《竹书纪年》里就出现了:“凤凰在庭,朱草生,嘉禾秀,甘露润,醴泉出,日月如合璧,五星如连珠。”

“五星连珠”是指水星、金星、火星、木星、土星五大行星聚集在同很小的范围内。比如传说刘邦进入咸阳时,“五星聚于东井”,这一年刘邦被封为汉王,史称汉元年。虽然“五星聚”这种现象可遇不可求,很少发生,可日月合朔,日月合璧,是每个月都有的。所以朔日初一总是古代王朝看重的日子,每逢初一、十五要举行大朝会。王昌龄有诗云“天子坐明堂,月朔朝诸侯”,帝王通过对朔日的强调,彰显顺应天意,君权神授。

阴阳历--以天文年和天文月作为日历的主要周期,例如:中国农历

阴历根据月亮圆缺变化的周期,即朔望月制定的。阴历的主要特点是:历月的长短依据天象即月相来确定,大月30日,小月29日。

图(1)没有闰月情况下朔日与冬至节气关系图

大年初一,王朝正朔

既然每个月的初一如此重要,正月初一,作为一年的第一天,就更加重要了。正月初一,又称为新年、元旦、元日、正朔。不过,从1912年民国元年开始,公历1月1日“抢”走了元旦这个名字。到1914年,民国三年,袁世凯大总统签署命令,把夏历的元旦改为春节(原来的春节指的是立春)。到今天,每年由紫金山天文台发布的历书中,我们的“农历年”新年第一天,依然是根据传统来确定的正月初一;而我们的“春节”,则是延续了民国大总统袁世凯的规定。正如本文开头所说,除夕是丁酉鸡年腊月三十,明天是戊戌狗年正月初一。

历史,就像地质学上的地层一样,叠加在我们的现实中。

在中国传统文化里,中央王朝要每年提前计算出来下一年的历书(包括日期、朔望、节气等详细信息),并把“皇历”颁发给各地和周边各国,这叫“班朔”或“颁正朔”。而各地诸侯、周边属国接受“皇历”,不仅仅是使用这一本历书,更重要的是臣服中央政权的标志,即“奉正朔”。正是一年之始,朔是一月之始,正朔就是正月初一,新年元旦,因此“正朔”代指的,是国家正统。

图片 4

白居易在《新乐府·骠国乐》记下了缅甸的骠国王子来朝贡的事件,诗中写道“骠国乐,骠国乐,出自大海西南角。雍羌之子舒难陀,来献南音奉正朔。”又比如“皇帝三年颁正朔,使君万里向交州”(元代宋沂《送傅与砺佐使安南》),“天王颁正朔,藩国荷恩荣”(明代王汝玉《送通政寺丞章有常使朝鲜》)则是中原政权派使节出使属国的记录。

在历史上,新王朝建立,都要改正朔,表示按上天意志完成改朝换代。在夏商周秦和汉初,连“正月”都改了。确定“正月”在古代称为“建正”,也就是以哪一个月为“正月”。古代把十二个月和十二地支对应,冬至所在的十一月为子月(子又指北方,冬至北斗的斗炳指北),十二月为丑月,一月为寅月。据说夏代以一月寅月为正月,称“建寅”;商代以十二月丑月为正月,称“建丑”;周代以十一月子月为正月,称为“建子”。以哪个月为一年开始的“正月”,这就是历史上的“三正论”。

其实历史还有过第四种。秦始皇灭六国一统天下之后,为了表示继承正统,以十月亥月为正月;刘邦建立汉朝,也自认为继承三代(可怜,秦始皇建立的中国历史上第一个大帝国被无视了),也以十月为正月,作为一年的开始。到了汉武帝元封七年实行《太初历》,才又按照夏历传统,把一年的开始放回到一月,后世两千多年沿用至今,“正月”也就固定指“一月”“寅月”了。这也是很多学者主张把中国传统历法称为“夏历”的原因。

既然“正朔”意味着以上天的权威号令天下,具有如此重要神圣的政治意义,历代王朝也自然都独占着开展天文工作的权利。“黄历”或“皇历”,只有中央王朝可以制定印刷,禁止民间私自印制,更不许自己编写,违者要杀头。比如在明朝《大统历》封面上印着“钦天监奏准印造大统历日颁行天下伪造者依律处斩!有能告捕者,官给赏银五十两,如无本监历日印信,即同私历。”

 

图片 5

图中上排数字是公历月的编号,黑色圆点代表朔日,黑色三角形代表冬至节气。图(2)显示了2012年有闰月的情况下朔日和冬至的关系:

太阳的年岁和属相

然后我还有另一个提问(坑):“一年有几个月?”诚然,公历一年是12个月。可夏历却是12个月,或者13个月。公历的闰年不过是在2月加入一天(闰日),夏历的闰年是多出一个月,比如今年丁酉鸡年就有个闰六月。

究其原因,无论是公历,还是夏历,都要以太阳的运行周期为依据。公历只根据太阳来确定日期,平均一年365.2425天,每400年要加入97个闰日(这是1582年罗马教皇格里高利十三世开始规定的,也叫格里高利历,它的前身则是凯撒大帝颁布的儒略历)。公历的好处是,每个月的天数都是确定的,置闰规则也容易理解,所以随着欧洲文明向全世界的传播,成为“公历”。

夏历由于实行朔望月(平均29.53天),一个月29天或30天,12个月只有354天(比如戊戌狗年),所以有时插入一个闰月,那一年就是13个月384天(比如丁酉鸡年)。这样长短搭配,平均年长依然是太阳回归年365.2422天。只是每一年、每个月的长度需要根据24节气、置闰规则、朔望月来具体计算。

所以夏历不是“阴历”(纯阴历指一年只有12个月,不考虑闰月的历法),而是阴阳合历——既要考虑朔望月周期,也考虑太阳回归年周期。可闰月的规定,一年开始(“岁首”)的漂移,也造成了很有趣的现象,比如会出现一年里有两个“立春节气”或者没有立春。

算法系列之二十,是为了庆祝日月合璧。对于按公历工作,按夏历过年,实行“双轨制”的我们来说,有些人对历法存在一些困惑,比如,按哪一种历法来过生日,哪一天才是“周岁”?其实无论公历还是夏历,本质上都是太阳、月亮运行的天文周期。公历的“周岁”对太阳周期是比较准确的,也是印在身份证上的。夏历的“周岁”是按月相再现的日子,对古人来说比较方便好记,今天还有很多人按夏历过生日。两种历法,各有特长,习惯就好,谈不上哪个“更好”。

至于属相,就更有趣了。比如许多人说,民间属相是按照“立春”(俗称“打春”)来算的,因为24节气是严格的太阳周期。可是如果我们仔细看手机上的日历,或印刷的历书,都是紫金山天文台按照传统规则颁布的。属相,或标准名字称为干支纪年,是以除夕、初一作为分界线,丁酉鸡年从正月初一开始,包括13个朔望月,一直到腊月三十;戊戌狗年也从正月初一开始,包括12个月,一直到腊月三十。也就说,“官方历书”是不承认“立春换属相”这种说法的。(杀头的罪)

图片 6十二生肖,图源:123rf

究其原因,在中国传统历法中,争论的焦点是哪个月是正月(“建正”“岁首”问题),哪一天是正月初一(计算准确的朔望月)。至于24节气,只是确定闰月的辅助,是“指导农事”和帝王祭天之用。一个是关乎天子权威的“正朔”,一个是指导农务的“辅助”,孰轻孰重?毋庸置疑,一年显然是从正月初一开始,到腊月三十结束。

当然,古人也知道一年三百六十五天,但除了天文学家之外,并不会认真对待它,知道一年三百六十日就可以了。比如我们会看到古人写“一年三百六十日,多是横戈马上行”(戚继光),“一年三百六十日,三百五十九日病”(陆游)。甚至古人会把“闰月”作为一种很有趣的现象来描述,比如“诗鬼”李贺写过 “十二月乐词”,其中第十三首写闰月。

河南府试十二月乐词(并闰月) 其十三 闰月(唐·李贺)

帝重光,年重时。

七十二候回环推,天官玉琯灰剩飞。

今岁何长来岁迟,王母移桃献天子。

有趣的是,“立春改属相”的说法,其实是从民国才有的。民国改用公历,并不重视夏历,称为“旧历”,甚至一度想强制彻底废除,只是传统习俗的力量过于强大,只好改为不干涉。既然不重视“旧历”了,民间也就有了印制“老黄历”的自由,爱属什么,也就由民间爱好者自己来制定了。而且由于公历的影响,我们才开始更重视24节气的阳历意义。你看我们现在新华字典上的“24节气”,说的就是公历日期,其实在明晚期以前,根本不知道“公历”为何物(感谢袁世凯大总统)。

(编辑:明天)

我国古人很早就开始关注天象,定昼夜交替为“日”,月轮盈亏为“月”,寒暑交替为“年”,在总结日月变化规律的基础上制定了兼有阴历月和阳历年性质的历法,称为中国农历。本文将介绍中国农历的历法规则、天干地支(Heavenly Stems,Earthly Branches)的计算方法以、二十四节气与中国农历的关系以及知道节气和日月合朔的精确时间的情况下推算中国农历年历的方法。

公历=阳历是世界通用的日期也就是我们平常的日期

图片 7

        在介绍中国农历的历法之前,必须要先介绍一下中国古代的纪年方法。中国古代用天干地支纪年,严格来讲,天干地支纪年以及十二属相并不是中国农历历法的一部分,但是在中国历史上直到今天,天干地支以及十二属相一直都是做为中国农历纪年关系密切的一部分而存在,因此这里先介绍一下天干地支纪年法以及十二属相。

农历=阴历是我国古代用来农耕的日期,也就是日历下面的小字所表示的日期

图(2)有闰月情况下朔日与冬至节气关系图

        中国古代纪年不用数字,而是采用天干地支组合。天干有十个,分别是:甲、乙、丙、丁、戊、己、庚、辛、壬、癸;地支有十二个,分别是:子、丑、寅、卯、辰、巳、午、未、申、酉、戌、亥。使用时天干地支各取一字,天干在前,地支在后,组合成干支,例如甲子、乙丑、丙寅等等,依次轮回可形成六十种组合,以这些天干地支组合纪年,每六十年一个轮回,称为一个甲子。实际上中国古代纪月、纪日以及纪时辰都采用干支方法,这些干支组合起来就是我们熟悉的生辰八字。十二属相又称“十二生肖”,由十一种源自自然界的动物:鼠、牛、虎、兔、蛇、马、羊、猴、鸡、狗、猪以及传说中的龙组成,用于纪年时,按顺序和十二地支组合成子鼠、丑牛、寅虎、卯兔、辰龙、巳蛇、午马、未羊、申猴、酉鸡、戌狗和亥猪。天干地支以及十二生肖常组合起来描述农历年,比如公历2011年就是农历辛卯兔年、2012年是壬辰龙年等等。

1,阳历--以地球绕太阳一周为一年所定出的历法。

 

        计算某一年的天干地支,有很多经验公式,如果知道某一年的天干地支,也可以直接推算其它年份的天干地支。举个例子,如果知道2000年是庚辰龙年,则2012年的干支可以这样推算:(2012-2000)% 10=2,2012年的天干就是从庚开始向后推2个天干,即壬;2012年的地支可以这样推算:(2012 - 2000)% 12 = 0,2012年的地支仍然是辰,因此2012年的天干地支就是壬辰,十二生肖龙年。对于2000年以前的年份,计算出年份差后只要将天干和地支向前推算即可。例如1995年的干支可以这样计算:(2000 – 1995) = 5,(2000 – 1995) = 5,庚向前推算5即是乙,辰向前推算5即是亥,因此1995年的干支就是乙亥,十二生肖猪年。这个干支推算算法的实现如下:

2,阴历--以太阴绕地球为一个月,12个月为一年所定出来的历法.。

通过计算得到能够覆盖两个冬至节气的所有朔日时间后,就可以着手建立公历日期与农历日期的对应关系。以图(1)所示的2011年为例,首先根据计算得到的15个朔日(2011年只会用到其中的前14个时间)时间,建立与2011年(公历年)有关的朔望月关系表:

  202 void CalculateYearGanZhi(int year, int *gan, int *zhi)

  203 {

  204     int sc = year - 2000;

  205     *gan = (7 sc) % 10;

  206     *zhi = (5 sc) % 12;

  207 

  208     if(*gan < 0)

  209         *gan = 10;

  210     if(*zhi < 0)

  211         *zhi = 12;

  212 }

3,公历--世界各国通用的历法。为太阳历,即阳历。

朔日编号

合朔时间

对应公历日期

月长

月名

1

01:35:39.90

2010-12-06

29

冬月

2

17:02:34.26

2011-01-04

30

腊月

3

10:30:42.67

2011-02-03

30

正月

4

04:45:59.44

2011-03-05

29

二月

5

22:32:15.13

2011-04-03

30

三月

6

14:50:31.79

2011-05-03

30

四月

7

05:02:32.51

2011-06-02

29

五月

8

16:53:54.10

2011-07-01

30

六月

9

02:39:45.06

2011-07-31

29

七月

10

11:04:06.43

2011-08-29

29

八月

11

19:08:50.09

2011-09-27

30

九月

12

03:55:54.64

2011-10-27

29

十月

13

14:09:40.97

2011-11-25

30

冬月

14

02:06:27.05

2011-12-25

29

腊月

15

15:39:23.99

2012-01-23

30

正月

获得2008年的干支纪年:

4,夏历--中华历代所用的历法,始自夏代,故称是阴历,历代都在不断修改,后来加上24节气后,成了阴阳合历。

表(2)2011年朔望月与公历日期关系表

    9 TCHAR *nameOfTianGan[COUNTS_FOR_TIANGAN] = { _T("甲"),_T("乙"),_T("丙"),_T("丁"),_T("戊"),_T("己"),_T("庚"),_T("辛"),_T("壬"),_T("癸") };

   10 TCHAR *nameOfDiZhi[COUNTS_FOR_DIZHI] = { _T("子"),_T("丑"),_T("寅"),_T("卯"),_T("辰"),_T("巳"),_T("午"),_T("未"),_T("申"),_T("酉"),_T("戌"),_T("亥") };

  146     int gan,zhi;

  147 

  148     CalculateYearGanZhi(2008, &gan, &zhi);

  149 

  150     text.Format(_T("农历【%s%s】%s年"),

  151                 year, m_curMonth, nameOfTianGan[gan - 1], nameOfDiZhi[zhi - 1], nameOfShuXiang[zhi - 1]);

5,农历--与夏历没有什么区别.历法为农事而立,所以中国人叫它农历.其中的24节气是按太阳年24等分而得,这是阳历部分.农历的月日及闰法属于阴历部分,编在一起就成了和阴阳合历.我们平常没注意,叫惯了"阴历"不加区分。

 

结果是:农历戊子鼠年。

1、阴历是农历,但农历不仅是阴历。我国自古流传下来的农历是阴阳合历,其中包括象这样“八月十五月亮圆”表示的以月亮周期记录的阴历。也包括“清明节”这样按“节气”来表达的、总在每年的4月5日这样的太阳历。

编号为1和2的两个朔日之间的朔望月是十一月,因为冬至节气落在这个朔望月,其它月的月名依次类推,正月的朔日就是春节。输出公历和农历双历时,以月(公历)为单位,从每月第一天开始,依次判断每一天属于哪个朔望月,确定这一天的农历月名,然后比较这一天和这个朔望月的朔日之间相差几天,记为农历日期。以2011年1月1日为例,这一天在2010年12月6日(2010年农历十一月的朔日)和2011年1月4日之间(2010年农历十二月的朔日),查表(1)可知对应的农历月是十一月,这一天和2010年12月6日相差26天,因此这一天的农历日期就是“廿七”。再以2011年2月3日(春节)这一天为例,查朔望月表得知2月3日属于从2月3日开始的朔望月,这个朔望月的月名是正月,而2月3日就是月首,农历日期是初一,正月初一就是春节。

 

所以,经常会在日历上看到“农历七月初七,大暑第九日”这样的表示,前面的七月初七是农历中的阴历表示法,而大暑第九日则是农历中的阳历表示法。

先来介绍两个函数,这两个函数分别用于计算节气和日月合朔发生的时间,函数算法的具体描述将在“日历生成算法”系列文章的第三篇《用天文方法计算二十四节气》和第四篇《用天文方法计算日月合朔》中介绍,此处只是简单介绍一下用法。首先是计算节气时间的函数:

        中国农历是以月亮运行周期为基础,结合太阳运行规律(二十四节气)制定的历法,农历月的定义规则就是中国农历历法的关键,因此要了解中国农历的历法规则,就必须知道如何定义月,如何设置闰月?中国农历的一年有十二个月或十三个月,但是正统的叫法只有十二个月,分别是正月、二月、三月、四月、五月、六月、七月、八月、九月、十月、冬月和腊月(注意,正统的中国农历是没有十一月和十二月的,如果你用的历法软件有显示农历十一月和农历十二月,就说明非常不专业)。中国民间常用“十冬腊月天”来形容寒冷的天气,其实指的就是十月,十一月和十二月这三个最冷的月份。一年有十三个月的情况是因为有闰月,多出来的这个闰月没有月名,只是跟在某个月后面,称为闰某月。比如公历2009年对应的农历乙丑年,就是闰五月,于是这一年可以过两个端午节。

2、从字面上理解,阳历是“太阳历”的简称。农历分为阴历和阳历就是这样的表示。但自从采用西方的“公元历法”,现在的阳历就基本上专门来表示也是“太阳历”的“公元历”。这主要跟我们的习惯有关。因为作为中国日期记录及节日的大部分,都是按照农历中的阴历来定义的。比如“除夕”就是腊月三十,年就是正月初一。端午节等等都如此。而用农历中的阳历来表示的好象只有一个算不上节日的“清明节”。农历中的阳历就是24节气,主要是为农业生产服务,说起来,农历中的阳历倒更能代表“农历”这个称谓。

    5 double CalculateSolarTerms(int year, int angle);

        中国农历为什么会有闰月?其实中国农历置闰月是为了协调回归年和农历年的矛盾。前面提到过,中国农历是一种阴阳历,农历的月分大月和小月,大月一个月是30天,小月一个月是29天。中国农历把日月合朔(太阳和月亮的黄经相同,但是月亮不可见)的日期定位月首,也就是“初一”,把月圆的时候定为望日,也就是“十五”,月亮绕地球公转一周称为一个朔望月。天文学的朔望月长度是29.5306日,中国农历以朔望月为基础,严格保证每个月的头一天是朔日,这就使得每个月是大月还是小月的安排不能固定,通常需要通过天文学观测和计算来确定。一个农历年由12个朔望月组成,这样一个农历年的长度就是29.5306  12 = 354.3672日,而阳历的一个天文学回归年是365.2422日,这样一个农历年就比一个回归年少10.88天,这个误差如果累计起来过16年就会出现“六月飞雪”的奇观了。为了协调农历年和回归年之间的矛盾,聪明的先人在天文观测的基础上,找到了“闰月”的方法,通过在适当的月份插入闰月来保证每个农历年的正月到三月是春季,四月到六月是夏季,七月到九月是秋季,十月到十二月是冬季,也就是说,让历法和天文气象能够基本对上,不至于出现“六月飞雪”。

您应该经常听到公历、农历、阳历、阴历等历法的叫法,但公历和阳历是一回事吗?阴历和农历又有什么联系和区别?

 

        那么多长时间增加一个闰月比较合适呢?最早人们推算是“三年一闰”,后来是“五年两润”,随着历法计算的精确,最终定型为“十九年七闰”。这个“十九年七闰”又是怎么算出来的呢?其实就是求出回归年日数和朔望月日数的最小公倍数,也就是m个回归年的天数和n个朔望月的天数相等,即:

还是先来看看历法的分类吧。古今中外历法的名目甚多,但大体上可以归纳为三种:阴历、阳历和阴阳历。

这个函数用于计算指定的年份(year参数)中,太阳在黄道上运行(视运动)到指定角度时的时间,angle可以设定节气发生时的角度,比如CalculateSolarTerms(2011, 270)就是计算2011年冬至的时间。这个函数返回的时间类型是儒略日,关于儒略日的说明请参考“日历生成算法”系列文章的第一篇《中国公历(格里历)》。

m  365.2422 = n  29.5306

阴历:这是人类历史上最早出现的历法。它的特点就是月的平均日数要以朔望月为基础,也就是符合月相的变化。一年为12个月,大月为30日,小月为29日。其中有6个大月和6个小月,全年共354天。可是,一年12个朔望月共长为29.53056×12=354.3671个平太阳日。这样,一年就比12个朔望月短0.3671日,3年就短约1天。为了使历年长度接近12个朔望月的长度,每3年就设置一个闰年,凡闰年就在12月末加1天,使12月从原来的小月变为大月,即从29日变为30日。阴历每年比回归年约短11日。因此,它的最大缺点是与四季寒暑无关。显而易见,这种历法对生活和生产,特别是对农业生产极不方便。因此,现在世界上除了伊斯兰教国家由于宗教关系仍在使用阴历外,其他国家早已不再使用阴历了。

        接下来介绍计算日月合朔时间的函数:

 

图片 8

    8 double CalculateMoonShuoJD(double tdJD);

这样m和n的比例就是29.5306 : 365.2422  19 : 235,按照这个最接近的整数倍数关系,每19个回归年需要添加的闰月就是:

阳历:阳历以地球绕太阳运动的周期为年的基础,以一个回归年长度为依据。它的月数和月所包含的日数都是人为规定的,没有任何天象依据。现在世界上大多数国家通用的公历就属于阳历。我国于1912年开始采用公历,但是,当时不用公元作为纪年。新中国成立后,于1949年改用公元作为纪元,普遍采用了公历。

 

 

阴阳历:我国传统历法农历就是一种阴阳历。顾名思义,阴阳历同时考虑太阳和月亮的运动,把回归年和朔望月并列为的基本周期。它的月像阴历那样以朔望月为基础,完全符合月相。它的年平均长度像阳历一样以回归年为标准,完全符合四季的交替。一年有12个月,大月为30日,小月为29日。至于哪一个月是大月,哪一个月为小月,则要根据朔和朔的日期间隔而定。两朔日期相隔为30日时定为大月,两朔日期相隔为29日时定为小月。全年平均为354日或355日,比回归年长度短了约11日,3年约差33日。为了使历法平均长度接近回归年,每3年就要设置一个闰年,闰年加1个月,该年为13个月,全年共384日或385日。然而,就是这样,阴阳历仍比回归年短。怎么办呢?我国古代的天文学家们早在公元前600年的春秋时代,就发现在19个阴历年中加入7个闰月,可以使阴阳历的历年平均长度更接近回归年。也就是说,在19年中应有12个平年和7个闰年。

这个函数返回指定时间附近的朔日时间,搜索的范围是tdJD参数指定时间的前一天到后29.5305天,tdJD参数和返回值的时间类型都是儒略日。

235 – 12  19 = 7

12×12 13×7=235个朔望月

        生成指定公历年份的公历和农历的双历年历的流程如下:

 

235个朔望月=29.53059×235=6939.6887个平太阳日

 

也就是“十九年七闰”的由来。但是需要注意的是,“十九年七闰”也并不是精确的结果,每19年就会有0.0892天的误差:

19个回归年=365.2422×19=6939.6018个平太阳日

图片 9

 

两者在19年中只差0.0869日,约合2小时5分8秒。当然,具体的置闰要根据实际天象计算结果来安排,哪一个月为闰月要根据24节气来定。

图(3)计算公农历双历年历的流程

19  365.2422 - 235  29.5306  0.0892

看到这儿,您应该不会再把阳历和公历、农历和阴历弄混了吧?

 

 

免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。

GetAllSolarTermsJD()函数从指定年份的指定节气开始,连续计算25个节气时间,时间可以跨年份,内部判断过冬至节气后自动转到下一年的节气继续计算:

这样每213年就会积累约1天的误差,因此,即使按照“十九年七闰”计算,中国农历每一两百年就需要修正一次。正因为这样,现行农历从唐代以后就已经不再遵守“十九年七闰”法,而是采用更准确的“中气置闰”法。“中气置闰”法更准确的名称应该是“定冬至”法,就是定两个冬至节气之间的时间为一个农历年,这样农历年的长度就和太阳回归年长度对应,不会产生误差。

  139 void CChineseCalendar::GetAllSolarTermsJD(int year, int start, double *SolarTerms)

  140 {

  141     int i = 0;

  142     int st = start;

  143     while(i < 25)

  144     {

  145         double jd = CalculateSolarTerms(year, st * 15);

  147         if(st == WINTER_SOLSTICE)

  148         {

  149             year ;

  150         }

  151         st = (st 1) % SOLAR_TERMS_COUNT;

  152     }

  153 }

        现在,我们知道农历通过置闰月的方式协调农历年和回归年长度不相等的问题,也知道了置闰的方法是“中气置闰”法,那么到底什么是“中气”,又是如何定中气置闰月呢?要回答这个问题,就需要介绍另一个天文现象――节气。二十四节气起源于黄河流域,远在春秋时代,就定出仲春、仲夏、仲秋和仲冬等四个节气。以后不断地改进与完善,到秦汉年间,二十四节气已完全确立,汉武帝太初元年(公元前104年)制定的《太初历》,则第一次从历法上明确了二十四节气的天文位置。

start参数是节气的索引,定义二十四节气的索引如下:

        地球沿着一个近似椭圆轨道绕太阳公转,这个公转轨道所在的平面就是“黄道面”,黄道面向外延伸与天球的交线就是“黄道”。古人由于观测条件限制,只能根据视觉感觉认为是太阳沿着黄道绕地球运转,因此设定太阳从黄经(黄道经度)零度起(以春分点为起点自西向东度量),将太阳沿黄经每运行15度所经历的时日称为“一个节气”。太阳每年运行360度,共经历二十四个节气,春季的节气有立春(315度)、雨水(330度)、惊蛰(345度)、春分(0度、360度)、清明(15度)和谷雨(30度),夏季的节气有立夏(45度)、小满(60度)、芒种(75度)、夏至(90度)、小暑(105度)和大暑(120度),秋季的节气有立秋(135度)、处暑(150度)、白露(165度)、秋分(180度)、寒露(195度)和霜降(210度)。冬季的节气有立冬(225度)、小雪(240度)、大雪(255度)、冬至(270度)、小寒(285度)和大寒(300度)。二十四节气又细分为十二节气和十二中气,二十四节气按照顺序排在奇数位置上的就是节气,排在偶数位置上的就是中气。也就是说,立春、惊蛰、清明、立夏、芒种、小暑、立秋、白露、寒露、立冬、大雪和小寒就是十二个节气,而雨水、春分、谷雨、小满、夏至、大暑、处暑、秋分、霜降、小雪、冬至和大寒就是十二个中气。二十四个节气平分在公历的12个月中,每月一节气一中气。二十四节气反映了太阳的周年运动(以地球为参照物的视运动),所以节气在现行的公历中日期基本固定,上半年在6日、21日,下半年在8日、23日,前后不差 1~2天。中国民间流传的《二十四节气歌》就是为了方便记忆这些节气:

   38 const int VERNAL_EQUINOX      = 0;    // 春分

   39 const int CLEAR_AND_BRIGHT    = 1;    // 清明

   40 const int GRAIN_RAIN          = 2;    // 谷雨

   41 const int SUMMER_BEGINS       = 3;    // 立夏

   42 const int GRAIN_BUDS          = 4;    // 小满

   43 const int GRAIN_IN_EAR        = 5;    // 芒种

   44 const int SUMMER_SOLSTICE     = 6;    // 夏至

   45 const int SLIGHT_HEAT         = 7;    // 小暑

   46 const int GREAT_HEAT          = 8;    // 大暑

   47 const int AUTUMN_BEGINS       = 9;    // 立秋

   48 const int STOPPING_THE_HEAT   = 10;   // 处暑

   49 const int WHITE_DEWS          = 11;   // 白露

   50 const int AUTUMN_EQUINOX      = 12;   // 秋分

   51 const int COLD_DEWS           = 13;   // 寒露

   52 const int HOAR_FROST_FALLS    = 14;   // 霜降

   53 const int WINTER_BEGINS       = 15;   // 立冬

   54 const int LIGHT_SNOW          = 16;   // 小雪

   55 const int HEAVY_SNOW          = 17;   // 大雪

   56 const int WINTER_SOLSTICE     = 18;   // 冬至

   57 const int SLIGHT_COLD         = 19;   // 小寒

   58 const int GREAT_COLD          = 20;   // 大寒

   59 const int SPRING_BEGINS       = 21;   // 立春

   60 const int THE_RAINS           = 22;   // 雨水

   61 const int INSECTS_AWAKEN      = 23;   // 惊蛰

春雨惊春清谷天,

 

夏满芒夏暑相连,

节气索引乘以15就是节气在黄道上对应的度数。GetNewMoonJDs()函数从指定时间开始连续计算15个朔日时间,从第一个冬至节气前的第一个朔日开始。15个朔日可以形成14个完整的朔望月,保证在有闰月的情况下也能包含两个冬至节气:

秋处露秋寒霜降,

  137 void CChineseCalendar::GetNewMoonJDs(double jd, double *NewMoon)

  138 {

  139     for(int i = 0; i < NEW_MOON_CALC_COUNT; i )

  140     {

  141         double shuoJD = CalculateMoonShuoJD(jd);

  142         NewMoon[i] = shuoJD;

  143 

  144         jd = 29.5; /*转到下一个最接近朔日的时间*/

  145     }

  146 }

冬雪雪冬小大寒,

BuildAllChnMonthInfo()函数根据15个朔日时间组成14个朔望月,根据相邻朔日的间隔计算出农历月天数用来判定大小月,并且从“十一月”开始依次为每个朔望月命名(月建名称):

每月两节不变更,

  170 bool CChineseCalendar::BuildAllChnMonthInfo()

  171 {

  172     CHN_MONTH_INFO info; //一年最多可13个农历月

  173     int i;

  174     int yuejian = 11;   //采用夏历建寅,冬至所在月份为农历11月

  175     for(i = 0; i < (NEW_MOON_CALC_COUNT - 1); i )

  176     {

  177         info.mmonth = i;

  178         info.mname = (yuejian <= 12) ? yuejian : yuejian - 12;

  179         info.shuoJD = m_NewMoonJD[i];

  180         info.nextJD = m_NewMoonJD[i 1];

  181         info.mdays = int(info.nextJD 0.5) - int(info.shuoJD 0.5);

  182         info.leap = 0;

  183 

  184         CChnMonthInfo cm(&info);

  185         m_ChnMonthInfo.push_back(cm);

  186 

  187         yuejian ;

  188     }

  189 

  190     return (m_ChnMonthInfo.size() == (NEW_MOON_CALC_COUNT - 1));

  191 }

最多相差一两天。

 

 

CalcLeapChnMonth()函数根据节气和朔日时间判断在两个冬至节气之间的农历年是否有闰月,判断的依据就是看第十四个朔日是否在第二个冬至节气之前,如果第十四个朔日发生在第二个冬至节气之前,就说明在两个冬至节气之间发生了十三次朔日,需要置闰月。因为农历中十二个中气属于哪个农历月是固定的,因此置闰月的过程就是依次判断十二个中气是否在对应的农历月中,如果本应该属于某个农历月的中气却没有落在这个农历月中,则这个农历月就是闰月,需要设置闰月标志,同时调整这个月之后的月名。调整农历月名的方法就是月名减一,比如原来是八月就要调整为七月,这样就将十三个月对应上了十二个月名(其中多出来的一个农历月被命名为闰某月)。如果节气和朔日发生在同一天,CalcLeapChnMonth()函数采用的是民间历法的规则,与现行历法一致:

传统上一个农历年起于冬至,终于冬至,因此要确定在哪一年置闰,主要看那一年两个冬至之间有几个朔望月,如果是12个朔望月,则不置闰,如果是十三个朔望月,则置闰月,至于闰几月,则要看节气而定。对于有13个朔望月的农历年,置闰月的规则就是从农历二月开始到十月,第一个没有中气的月就是闰月,这个没有中气的朔望月跟在哪个月后面就是闰几月。为什么会有没有中气的朔望月呢?黄道上两个中气之间相隔30度,一个回归年的长度是365.2422日,则两个中气之间的平均间隔是365.2422 12 = 30.4368日,但是因为地球轨道是椭圆轨道,因此相邻的两个中气的时间间隔是不均匀的,比如在远地点附近的中气间隔就会长一点,最长可能是31.45天。而农历的朔望月平均长度是29.5306日,这样就会出现某个朔望月刚好落在两个中气之间的情况,比如,某个月的上一个月月末是一个中气,但是下一个中气落在这个月的下一个月的头几天里,这样这个月就没有中气了。举个例子,2001年农历辛已年的四月二十九(公历5月21日)是小满,农历四月之后的这个朔望月从公历5月23日持续到公历6月20日,而小满后的下一个中气夏至是在公历的6月21日,也就是农历四月的下下个月的初一,这样农历四月后的这个月就没有中气,跟在四月之后,就称为闰四月。

  194 void CChineseCalendar::CalcLeapChnMonth()

  195 {

  196     assert(m_ChnMonthInfo.size() > 0); /*阴历月的初始化必须在这个之前*/

  197 

  198     int i;

  199

  200     if(int(m_NewMoonJD[13] 0.5) <= int(m_SolarTermsJD[24] 0.5)) //第13月的月末没有超过冬至,说明今年需要闰一个月

  201     {

  202         //找到第一个没有中气的月

  203         i = 1;

  204         while(i < (NEW_MOON_CALC_COUNT - 1))

  205         {

  206 

  207             /*m_NewMoonJD[i 1]是第i农历月的下一个月的月首,本该属于第i月的中气如果比下一个月

  208               的月首还晚,或者与下个月的月首是同一天(民间历法),则说明第i月没有中气*/

  209             if(int(m_NewMoonJD[i 1] 0.5) <= int(m_SolarTermsJD[2 * i] 0.5))

  210                 break;

  211             i ;

  212         }

  213         if(i < (NEW_MOON_CALC_COUNT - 1)) /*找到闰月,对后面的农历月调整月名*/

  214         {

  215             m_ChnMonthInfo[i].SetLeapMonth(true);

  216             while(i < (NEW_MOON_CALC_COUNT - 1))

  217             {

  218                 m_ChnMonthInfo[i ].ReIndexMonthName();

  219             }

  220         }

  221     }

  222 }

        由于节气在回归年中是均匀分布的,因此公历中的节气日期基本上是固定的,比如立春是在公历的2月3-5日,不会超出这个日期范围,这也就是《二十四节气歌》所说的:每月两节不变更,最多相差一两天。但是在中国农历中哪个中气属于哪个月是有规定的,雨水是正月的中气,春分是二月的中气,谷雨是三月的中气,小满是四月的中气,夏至是五月的中气,大暑是六月的中气,处暑是七月的中气,秋分是八月的中气,霜降是九月的中气,小月是十月的中气,冬至是十一月的中气,大寒是十二月的中气。

        从理论上讲,本文介绍的算法在精度允许的范围内可以计算前后几千年的农历年历,但是对古代的农历计算需要小心。首先是“平朔”和“定朔”的问题,唐代以前使用的是平朔方法定月首,本文介绍的计算方法采用的是“定朔”方法,因此计算出的年历与唐代以前的历史会不一致。另外,即是在唐代以后采用“定朔”的历法,因为古代天文观测和计算受条件限制,可能不够精确,因此与现在用天文算法计算出的结果可能并不一致。所以对历史农历的计算应该以历史事实为主,天文计算为辅,当计算与历史不一致时,要根据历史数据进行校正。Calendar.exe是根据本文介绍的算法编写的日历小程序,没有太多的功能,主要是为了验证算法,因为没有历史数据用于修正结果,因此不支持1601年以前的农历计算(也就是说按照天文算法计算出来的结果可能和实际历史上的历法不符)。

        在了解了农历与节气的关系以及农历如何置闰月的方法之后,还需要解决一个问题才能着手农历年历的推算,那就是如何确定农历年的开始,或者说哪个月的初一是农历新年的开始?要回答这个问题,就需要了解中国农历特有的“月建”问题。

图片 10

        中国农历是阴阳合历,需要同时考虑太阳和月亮的位置。所以在确定岁首(元旦)时,需要先确定它在某个季节,然后再选定与这个季节相近的朔望月作为岁首。由于一岁(一个回归年)和12个阴历月并不相等,相差约10.88天,因此每隔三年需要设置一个闰月调整季节。中国上古的天文学家想出了一个简便的方法判断月序与季节的关系,这就是以傍晚时北斗七星的斗柄的指向确定月序,称为“十二月建”。从北方起向东转,将地面划分为十二个方位,傍晚时北斗所指的方位,就是该月的月建,其子月为冬至所在之月,对应十一月,丑月是冬至所在之月的次月,对应十二月,寅月在丑月之后,对应正月。中国在历史上的不同时期,多次修改过岁首(元旦)的起始月份,上古时代就有“三正”之说,所谓“三正”,就是“夏正建寅、殷正建丑、周正建子”,意思是夏历以寅月(正月)为岁首,殷历以丑月(十二月)为岁首,周历以子月(十一月)为岁首。从秦代到西汉前期又采用秦历,秦历建亥,也就是以亥月作为岁首之月,汉武帝太初元年(公元104年)改用太初历,重新适用建寅的夏历,以寅月(正月)为岁首。在这之后的两千多年时间里,除王莽和魏明帝一度改用建丑的殷历,唐武后和肃宗时改用建子的周历外,各个朝代均使用建寅的夏历直到清朝末年。辛亥革命胜利以后,南京国民政府将公历1月1日改为元旦,但是人们仍习惯称农历的正月初一为元旦。新中国成立初期召开的第一届政治协商会议,正式将公历的1月1日确定为元旦,将农历的正月初一定为“春节”,也就是说,农历的岁首仍然采用夏历从寅月(正月)开始。

图(5)演示程序的界面

        了解了“月建”问题,就解决了农历朔望月与公历月的对应关系,那就是冬至节气所在的朔望月就是农历的子月,对于目前适用的夏历建寅的月建体系,就意味着冬至节气所在的朔望月是农历的十一月,只要找到这个朔望月的起始日(日月合朔发生的时刻所在的那一日),就找到了公历的日期月农历日期的对应关系。下面总结一下中国农历历法的基本法则:

 

 

小知识1:民间历法和历理历法

1、严格以日月合朔发生时刻为月首,这一天定为初一,通过计算两次日月合朔的时间间隔确定每月是29天还是30天;

    新中国成立以后没有颁布新的“官方农历历法”,将历法和政治分离体现了时代的进步,但是由于没有 “官方历法”,也引起了一些问题。比如我国现在采用的农历历法是《时宪历》,它源于清朝顺治年间(公元1645)颁布的《顺治历》,它有两个不足之处:一个是日月合朔和节气的时间以北京当地时间为准,也就是东经116度25分的当地时间,其节气和新月的观察只适用于中原地区。其它经度的地方,因为时间的关系,对导致日月合朔和节气时间的差异导致置闰和月顺序各不相同。另一个不足之处就是日月合朔时间和节气时间判断不精确,如果日月合朔时间和节气时间在同一天,不管具体的时间是否有先后,一律将此节气算做新月中的节气,这样一来,如果这个节气是中气,就会影响到闰月的设置。历理历法针对这两点进行了改进,对节气时间和日月合朔时间统一采用东经120度即东八区标准时,这样在任何时区的节气和置闰结果都是一样的,以东八区标准时为准。对于节气时间和日月合朔时间在同一天的情况,精确计算到时、分、秒,只有日月合朔时间在节气时间之前,这个节气才包含在次月内。历理历法从理论上讲更符合现代天文学的精确计算,但是需要注意的是,历理历法仍然只是存在于理论上的历法,我国现行的农历历法依然是民间历法《时宪历》或《顺治历》。

2、月以中气得名,冬至节气总是出现在农历十一月,包含雨水中气的月为正月(即寅月),月无中气者为闰月,与前一个月同名;

 

3、从某一年的冬至后第一天开始,到下一个冬至这段时间内,如果有十三个朔望月出现,则此期间要增加一个闰月,从二月到十月,第一个没有中气的月就是闰月,如果在此期间有超过两个朔望月没有中气,则只有第一个没有中气的朔望月是闰月;

 

4、农历年以正月初一为岁首(关于农历岁首的说法,请参考文末附加的《小知识5:正月初一和立春节气》),以腊月(十二月)廿九或三十为除夕;

小知识2:通式寿星公式

5、如果节气和日月合朔在同一天,则该节气是这个新朔望月的节气。(民间历法)

“通式寿星公式”是前人整理出来的一个用于计算每年立春日期的经验公式:

   

Date = 向下取整(Y * D C) - L

        规则5对节气和朔日在同一天的处理,采用了民间历法的处理原则,关于民间历法和历理历法的区别,请参考文末附加的《小知识1:民间历法和历理历法》。

其中,Y是年份,D的值是0.2422,C是经验值,取决于节气和年份,对于21世纪,立春节气的C值是4.475,春分节气的C值是20.646等等;

        了解了农历历法的基本法则后,就可以根据历法进行农历年历的推算。农历年历的推算是一件很复杂的事情,需要知道每年二十四个节气和本年内每次日月合朔的精确时间,这些时间的获取比较困难。现在有很多可以显示农历的日历软件,其实并不计算这些时间,而是事先从权威机构(如紫金山天文台)获取这些经过推算的时间,然后用各种方法将这些信息存储在设计好的数据结构中。当计算农历时采用查表的方法获取每年的二十四节气日期、大小月情况以及闰月情况,这样的软件受数据量的限制,往往只能显示近一两百年的年历。

L是闰年数,其计算公式为:

        还有一种确定节气时间和朔日时间的方法,就是在已知某个节气或朔日的精确时间后,通过某些规律先前或向后推算其它节气或朔日的时间。有一些经验公式可以用来计算节气发生的日期,比如“通式寿星公式”,可以计算出某一年的某个节气时间,但是只能精确到日。关于“通式寿星公式”的详细内容,请参考文末附加的《小知识2:通式寿星公式》。至于精确的节气或朔日时间,也只能从权威机构获取。以节气的时间推算为例,二十四个节气就是黄道上的24各点,由于地球运动受其它天体的影响,导致这些节气在每年的时间是不固定的,但是这些节气之间的间隔时间基本上可以看作是固定的,下表就是二十四节气的时间间隔表:

L = 向下取整(Y/4) - 向下取整(Y/100)  向下取整(Y/400)

 

 

节气名

与上一节气之间的时间差

与小寒节气的累积时间差

小寒

1271448.00

0.00

大寒

1272494.40

1272494.40

立春

1275526.20

2548020.60

雨水

1282123.20

3830143.80

惊蛰

1290082.80

5120226.60

春分

1300639.20

6420865.80

清明

1311153.00

7732018.80

谷雨

1323253.80

9055272.60

立夏

1333685.40

10388958.00

小满

1344107.40

11733065.40

芒种

1351227.00

13084292.40

夏至

1357299.60

14441592.00

小暑

1358968.80

15800560.80

大暑

1358786.40

17159347.20

立秋

1354419.00

18513766.20

处暑

1348236.00

19862002.20

白露

1339003.20

21201005.40

秋分

1328654.40

22529659.80

寒露

1317185.40

23846845.20

霜降

1305760.80

25152606.00

立冬

1295081.40

26447687.40

小雪

1285764.00

27733451.40

大雪

1278469.80

29011921.20

冬至

1273556.40

30285477.60

用“通式寿星公式”确定2011年立春日期的过程如下:

 

L = int(2011/4) – int(2011/100) int(2011/400) = 502 – 20 5 = 487

表(1)二十四节气时间间隔表(单位:秒钟)

 

 

Date = int(2011×0.2422 4.475)- 487 = 491 – 487 = 4

已知1900年小寒时刻为1月6日2:05:00,以这个节气时刻为基准,推算其它年份节气的算法实现如下:

 

    8 static double s_stAccInfo[] =

    9 {

   10     0.00, 1272494.40, 2548020.60, 3830143.80, 5120226.60, 6420865.80,

   11     7732018.80, 9055272.60, 10388958.00, 11733065.40, 13084292.40, 14441592.00,

   12     15800560.80, 17159347.20, 18513766.20, 19862002.20, 21201005.40, 22529659.80,

   13     23846845.20, 25152606.00, 26447687.40, 27733451.40, 29011921.20, 30285477.60

   14 };

   15 

   16 //已知1900年小寒时刻为1月6日02:05:00

   17 const double base1900_SlightColdJD = 2415025.5868055555;

   18 

   19 double CalculateSolarTermsByExp(int year, int st)

   20 {

   21     if((st < 0) || (st > 24))

   22         return 0.0;

   23 

   24     double stJd = 365.24219878 * (year - 1900) s_stAccInfo[st] / 86400.0;

   25 

   26     return base1900_SlightColdJD stJd;

   27 

   28 }

所以,2011年的立春日期是2月4日。

base1900_SlightColdJD是北京时间1900年1月6日凌晨2:05:00的儒略日数,CalculateSolarTermsByExp()函数返回指定年份的节气的儒略日数。已知某个朔日的精确时间推算其它朔日时间的方法也类似,以朔望月的长度为单位向前或向后累加即可。

 

        这种推算的方法是建立在地球回归年的长度是固定365.2422天、节气的间隔是绝对固定的、朔望月长度是平均的29.5305天等假设之上的,由于天体运动的互相影响,这种假设不是绝对成立的,因此这种推算方法的误差很大。以CalculateSolarTermsByExp()函数为例,计算1900年前后30年内的节气时间的误差还可以控制在30分钟以内,但是到2000年的时候误差已经超过130分钟了。人们还总结出了计算节气和朔日时间的两个经验公式,本文末尾附加的《小知识3:计算节气和朔日的经验公式》一节会详细介绍这两个公式,不过这两个公式的结果也只能精确到日,不能提供10秒以内精度的时间。要想精确地获得几千年乃至更长时间范围内任意一年的节气发生时间和日月合朔时间,就只能采用“天文算法”。

 

 

小知识3:计算节气和朔日的经验公式

《继续:天文算法计算农历。。。》

    以1900年1月0日(星期日)为基准日,之后的每一天与基准日的差值称为“积日”, 1900年1月1日的积日是1,以后的时间依次类推,则计算第y年第x个节气的积日公式是:

 

 

F = 365.242 * (y – 1900) 6.2 15.22 *x - 1.9 * sin(0.262 * x)

 

其中x是节气的索引,0代表小寒,1代表大寒,其它节气按照顺序类推。

 

计算从1900年开始第m个朔日的公式是:

 

M = 1.6 29.5306 * m 0.4 * sin(1 - 0.45058 * m)

 

 

小知识4:平朔和定朔

    中国农历的朔望月长度是平均29.5305天,所以农历月就有大月30天,小月29天之分,从先秦时期到唐代,农历历法均是采用大小月轮流交替的方式设置每个农历月的天数,只有少数情况下才出现连续两个大月的情况,采用这种方式的历法就称为“平朔”。“平朔”历法简单,但是不能保证日月合朔发生在初一这一天,有可能是上月的月末一天,也有可能是本月初二。南北朝时期,一种新的历法被提出来,这种历法严格按照日月合朔为月初制定农历月,采用这种方式的历法就称为“定朔”。“定朔”历法严格将日月合朔时间确定月初,因为月球公转是椭圆轨道,速度并不是均匀,所以会发生连续多个大月或连续多个小月的情况,导致“定朔”历法推广遇到很大的阻力,直到唐代,中国历法才全面弃用“平朔”,改用“定朔”。

 

 

小知识5:正月初一和立春节气

    立春是二十四节气之首,所以古代民间都是在“立春”这一天过节,相当于现代的春节(中国古代即是节气也是节日的情况很多,比如清明、冬至等等)。1911年,孙中山领导的辛亥革命建立了中华民国,在从历法上正式把农历正月初一定为“春节”,把公历1月1日定为“元旦”,也就是“新年”。农历年从正月初一开始没有争议,但是农历生肖年从何时开始却一直有争议,目前多数人都认为“立春”节气是农历生肖年的开始。因为在中国古代历法中,十二生肖的计算与天干地支有很大关系,所以在“论天干地支、计算廿四节气”的情况下,“立春”节气应该是新生肖的开始。对于普通老百姓来说,习惯于认为正月初一是生肖年的开始,因此,正月初一和“立春”节气之间出生的小孩,在确定属相的时候就有点麻烦了。属龙还是属蛇?这是个问题。

本文由betway必威官网手机版发布于科学知识,转载请注明出处:算法系列之二十,是为了庆祝日月合璧

关键词:

上一篇:量子材料科学中心江颖,量子森林等入选

下一篇:没有了