这篇文章主要介绍了C++计算中国农历的深入浅析,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
image所谓的“天文算法”,就是利用经典力学定律推导行星运转轨道,对任意时刻的行星位置进行精确计算,从而获得某种天文现象发生时的时间,本文介绍的农历年历推算是在已经通过天文算法获得了精确的节气时间和日月合朔时间的基础上进行的。
加小编C/C++编程学习群:825414254获取C++项目资料
image由农历历法规则可知,上一个公历年的冬至()所在的朔望月是上一个农历年的十一月(冬月),所以在进行节气计算时,需要计算包括上一年冬至节气在内的二十五个节气,才能对应上上一个农历年的十一月和当前农历年的十一月。在计算与之对应的朔日时,考虑到有闰月的情况,需要从上一年冬至节气前的第一个朔日,连续计算15个朔日才能保证覆盖两个冬至之间的一整年时间,图(1)显示了2011年没有闰月的情况下朔日和冬至的关系:
image图(1)没有闰月情况下朔日与冬至节气关系图
图中上排数字是公历月的编号,黑色圆点代表朔日,黑色三角形代表冬至节气。图(2)显示了2012年有闰月的情况下朔日和冬至的关系:
image图(2)有闰月情况下朔日与冬至节气关系图
通过计算得到能够覆盖两个冬至节气的所有朔日时间后,就可以着手建立公历日期与农历日期的对应关系。以图(1)所示的2011年为例,首先根据计算得到的15个朔日(2011年只会用到其中的前14个时间)时间,建立与2011年(公历年)有关的朔望月关系表:
image表(2)2011年朔望月与公历日期关系表
首先是计算节气时间的函数:
<pre style="margin: 0px; padding: 0px; border: 0px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-variant-numeric: inherit; font-variant-east-asian: inherit; font-weight: 400; font-stretch: inherit; font-size: 18px; line-height: inherit; font-family: inherit; vertical-align: baseline; word-break: break-word; color: rgb(93, 93, 93); letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration-style: initial; text-decoration-color: initial;">
5 double CalculateSolarTerms(int year, int angle);
</pre>
这个函数用于计算指定的年份(year参数)中,太阳在黄道上运行(视运动)到指定角度时的时间,angle可以设定节气发生时的角度,比如CalculateSolarTerms(2011, 270)就是计算2011年冬至的时间。
接下来介绍计算日月合朔时间的函数:
<pre style="margin: 0px; padding: 0px; border: 0px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-variant-numeric: inherit; font-variant-east-asian: inherit; font-weight: 400; font-stretch: inherit; font-size: 18px; line-height: inherit; font-family: inherit; vertical-align: baseline; word-break: break-word; color: rgb(93, 93, 93); letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration-style: initial; text-decoration-color: initial;">
8 double CalculateMoonShuoJD(double tdJD);
</pre>
这个函数返回指定时间附近的朔日时间,搜索的范围是tdJD参数指定时间的前一天到后29.5305天,tdJD参数和返回值的时间类型都是儒略日
生成指定公历年份的公历和农历的双历年历的流程如下:
imageGetAllSolarTermsJD()函数从指定年份的指定节气开始,连续计算25个节气时间,时间可以跨年份,内部判断过冬至节气后自动转到下一年的节气继续计算:
imagestart参数是节气的索引,定义二十四节气的索引如下:
image节气索引乘以15就是节气在黄道上对应的度数。GetNewMoonJDs()函数从指定时间开始连续计算15个朔日时间,从第一个冬至节气前的第一个朔日开始。15个朔日可以形成14个完整的朔望月,保证在有闰月的情况下也能包含两个冬至节气:
imageBuildAllChnMonthInfo()函数根据15个朔日时间组成14个朔望月,根据相邻朔日的间隔计算出农历月天数用来判定大小月,并且从“十一月”开始依次为每个朔望月命名(月建名称):
image如果节气和朔日发生在同一天,CalcLeapChnMonth()函数采用的是民间历法的规则,与现行历法一致:
image从理论上讲,本文介绍的算法在精度允许的范围内可以计算前后几千年的农历年历,但是对古代的农历计算需要小心。
根据本文介绍的算法编写的日历小程序,没有太多的功能,主要是为了验证算法,因为没有历史数据用于修正结果,因此不支持1601年以前的农历计算(也就是说按照天文算法计算出来的结果可能和实际历史上的历法不符)。
image
网友评论