算法系列之二十:计算中国农历(一)

算法系列之二十:计算中国农历(一)

原创吹泡泡的小猫最后发布于2013-07-0100:18:50阅读数65351收藏

展开

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

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

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

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

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

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

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

202voidCalculateYearGanZhi(intyear,int*gan,int*zhi)

203{

204intsc=year-2000;

205*gan=(7+sc)%10;

206*zhi=(5+sc)%12;

207

208if(*gan<0)

209*gan+=10;

210if(*zhi<0)

211*zhi+=12;

212}

获得2008年的干支纪年:

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

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

146intgan,zhi;

147

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

149

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

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

结果是:农历戊子鼠年。

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

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

m365.2422=n29.5306

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

235–1219=7

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

19365.2422-23529.53060.0892

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

春雨惊春清谷天,

夏满芒夏暑相连,

秋处露秋寒霜降,

冬雪雪冬小大寒,

每月两节不变更,

最多相差一两天。

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

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

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

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

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

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

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

节气名

小寒

1271448.00

0.00

大寒

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

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

8staticdoubles_stAccInfo[]=

9{

100.00,1272494.40,2548020.60,3830143.80,5120226.60,6420865.80,

117732018.80,9055272.60,10388958.00,11733065.40,13084292.40,14441592.00,

1215800560.80,17159347.20,18513766.20,19862002.20,21201005.40,22529659.80,

1323846845.20,25152606.00,26447687.40,27733451.40,29011921.20,30285477.60

14};

15

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

17constdoublebase1900_SlightColdJD=2415025.5868055555;

18

19doubleCalculateSolarTermsByExp(intyear,intst)

20{

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

22return0.0;

23

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

THE END
1.公历转农历生肖干支纪年节气算法研究和C程序实现农历的那些事儿(一) 香港天文台农历数据(txt版) 香港天文台农历数据(pdf版) 二、关于农历 查阅了大量关于公历转农历的博文之后,明确了:所谓的公历转农历算法即系基于查表法推算。因为农历无明显规律,数据需要天文台观测得到,因此无法用公式将公历转成农历。 https://blog.csdn.net/Stack_/article/details/119980697
2.国历和农历怎么转换6、国历与农历的换算公式 求教高人!!! 你指的是公历与农历的换算公式吧?这个算法复杂,我可以提供C或C++的API函数给你,不知道你是用什么语言来编的? 7、转换农历国历 网友分享:你好,国历1997.13,转换为农历是1997年1月7日,星星期四;国历1997.1,转换为农历是1996年12月24日,星期六。 https://www.105188.com/sh/618011.html
3.中国农历,有详细的阴历算法中国农历,有详细的阴历算法_农历算法,农历算法Et**on 上传43.55 KB 文件格式 rar 这本来是我为一个商业PDA产品开发的日历程序,最近移植于PC机上, 所以算法 和数据部分是用纯C++写的,不涉及MFC,所有的代码都是以短节省存储空间为主要目 的. 很高兴你对这些代码有兴趣,你可以随意复制和使用些代码,唯一有一点小小https://www.coder100.com/index/index/content/id/1356739
4.农历日历的计算方法理想股票技术论坛这篇文章将介绍农历日历的计算方法,包括如何计算农历日期以及应用的农历算法。了解这些计算方法可以帮助我们准确地确定农历日期,从而更好地了解传统农历文化和传统节日的日期。 ,理想股票技术论坛https://www.55188.com/tag-5268596.html
5.博大精深的农历算法php教程博大精深的 农历算法 /*** Lunar calendar 博大精深的农历* 原始数据和算法思路来自 S&SLab http://www.focus-2000.com 可惜网站好像关了*//*农历每月的天数。每个元素为一年。每个元素中的数据为:[0]是闰月在哪个月,0为无闰月;[1]到[13]是每年12或13个月的每月天数;[14]是当年的天干次序,[15]是https://www.php.cn/php-weizijiaocheng-318541.html
6.农历的算法是怎么算的农历的算法是怎么算的错过花期 精选回答 农历按照全年的自然日划分为四季、二十四节气和年节。 农历的二十四节气包括:春季的立春、雨水、惊蛮、春分、清明、谷雨;夏季的立夏、小满、芒种、夏至、小暑、大暑;秋季的立秋、处暑、白露、秋分、寒露、霜降;冬季的立冬、小雪、大雪、冬至、小寒、大寒。此外,全年中的https://edu.iask.sina.com.cn/jy/3qDa0bwIqY5.html
7.阳历与农历转换的算法,,CIO之家下面是一个关于VB的农历算法 '日期数据定义方法如下 '前12个字节代表1-12月为大月或是小月,1为大月30天,0为小月29天; '第13位为闰月的情况,1为大月30天,0为小月29天; '第14位为闰月的月份,如果不是闰月为0,否则给出月份,10、11、12分别用A、B、C来表示,即使用16进制; http://km.ciozj.com/Detail.aspx?AI=48791
8.VB计算农历的算法.NET教程,VB.Net语言下面是一个关于vb的农历算法 日期数据定义方法如下 前12个字节代表1-12月为大月或是小月,1为大月30天,0为小月29天, 第13位为闰月的情况,1为大月30天,0为小月29天,第14位为闰月的月 份,如果不是闰月为0,否则给出月份,10、11、12分别用a、b、c来表 示,https://www.west.cn/www/info/22131-1.htm
9.python实现的阳历转阴历(农历)算法Flex公历转农历算法 Flex公历转换成农历的类(参考C++版本)。 使用方式: new ChineseDate(new Date()).date 输出公历日期对应的农历格式。 上传者:liu_you时间:2009-12-25 Python实现公历(阳历)转农历(阴历)的方法示例 本文实例讲述了Python实现公历(阳历)转农历(阴历)的方法。分享给大家供大家参考,具体如下: 两https://www.iteye.com/resource/weixin_38721119-13777616
10.教你用SQL生成一张带「农历」的日期维度表有不少同学留言该如何解决农历的问题,今天就告诉大家具体操作方法。农历与世界通用的日历有所区别,是科学家演算出来的,目前为止只有到2049年的,以后的有了还可以加入! 本文转载自微信公众号「SQL数据库开发」,作者丶平凡世界 。转载本文请联系SQL数据库开发公众号。 https://www.51cto.com/article/646091.html
11.公历转农历怎么个计算方法?标题: Re: 公历转农历怎么个计算方法? 发信站: 水木社区 (Wed Nov 22 10:51:46 2023), 站内 网页版的日历,查看源码就可以,特别是宝岛的人写的,对农历算法有研究 -- ※ 来源:·https://exp.mysmth.net·[FROM: 182.239.114.*] 查看 发信 加好友 返回顶部 lixz1988 回复 转寄 转载 关注 搜http://images.newsmth.net/nForum/article/Programming/211883?au=lixz1988
12.农历计算方法探秘(农历如何计算)2.置闰法则:农历通过设置闰月来调整月亮和太阳的周期差异。具体方法是:以19年为一个周期,其中12个平年各设12个月,7个闰年各设13个月。闰月的设置是根据天文算法和历法规则确定的,通常在农历的特定年份中插入一个额外的月份。 3.干支纪年:农历还结合了干支纪年法,以10天干和12地支的组合形成一个60年的循环。每https://www.zaixianjisuan.com/jisuanzixun/nonglijisuanfangfatanmi.html
13.农历计算方法所以计算农历需要先找出气朔,计算气朔则需计算太阳和月亮的黄经,现代天文学使用行星历表计算天体位置。python有第三方库提供相关功能,本文提供的算法以PyEphem库为例,利用太阳黄经计算节气,由SolarTerms函数处理,合朔则直接使用库中提供的next_newmoon函数进行计算。 https://www.jianshu.com/p/d3b63ee7492f
14.一种公历到农历日期转换算法的实现本文主要从单片机软件实现角度介绍一种公历到农历转换的算法思想, 算法采用MCS-51 指令系统实现。并给出程序流程图,另外对二十四节气和生肖的算法也做详细介绍。关键词:单片机;MCS-51 指令系统Abstract: This paper introduces the realization and algorithm of the transform between Gregorian calendar and lunar https://m.elecfans.com/article/39160.html
15.属兔的和什么属相最配接亲网三、属相算法 1、农历算法 以除夕为分界点,也就是我们说的农历新年(大年初一)为起点计算生肖的方法出现比较晚,最早记载出现在北宋,现在很多人比较认同这个。民俗专家们认为,属相不应该按二十四节气来算,毕竟春节是农历新年的开始,也是农历生肖年的开始,属相自然应从正月初一算起。 https://www.jieqinwang.com/baike/96698
16.C++实现公历转农历的算法CPPX的博客C++实现公历转农历的算法 由于C++语言诞生的比较早,所以不像.NET那样官方自带公历转农历的代码库,因此只能通过自己来实现今天是农历几月几日星期几的查询. 以下文件在linux g++ (GCC) 4.1.2 环境编译通过 //file: lunarday.h //author: cuichaox@gmail.comhttp://www.cppblog.com/ctou45/archive/2012/08/21/187846.aspx