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

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

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

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

朔日编号

对应公历日期

月长

月名

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

正月

4

04:45:59.44

2011-03-05

二月

5

22:32:15.13

2011-04-03

三月

6

14:50:31.79

2011-05-03

四月

7

05:02:32.51

2011-06-02

五月

8

16:53:54.10

2011-07-01

六月

9

02:39:45.06

2011-07-31

七月

10

11:04:06.43

2011-08-29

八月

11

19:08:50.09

2011-09-27

九月

12

03:55:54.64

2011-10-27

十月

13

14:09:40.97

2011-11-25

14

02:06:27.05

2011-12-25

15

15:39:23.99

2012-01-23

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

编号为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日就是月首,农历日期是初一,正月初一就是春节。

5doubleCalculateSolarTerms(intyear,intangle);

8doubleCalculateMoonShuoJD(doubletdJD);

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

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

139voidCChineseCalendar::GetAllSolarTermsJD(intyear,intstart,double*SolarTerms)

140{

141inti=0;

142intst=start;

143while(i<25)

144{

145doublejd=CalculateSolarTerms(year,st*15);

147if(st==WINTER_SOLSTICE)

148{

149year++;

150}

151st=(st+1)%SOLAR_TERMS_COUNT;

152}

153}

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

38constintVERNAL_EQUINOX=0;//春分

39constintCLEAR_AND_BRIGHT=1;//清明

40constintGRAIN_RAIN=2;//谷雨

41constintSUMMER_BEGINS=3;//立夏

42constintGRAIN_BUDS=4;//小满

43constintGRAIN_IN_EAR=5;//芒种

44constintSUMMER_SOLSTICE=6;//夏至

45constintSLIGHT_HEAT=7;//小暑

46constintGREAT_HEAT=8;//大暑

47constintAUTUMN_BEGINS=9;//立秋

48constintSTOPPING_THE_HEAT=10;//处暑

49constintWHITE_DEWS=11;//白露

50constintAUTUMN_EQUINOX=12;//秋分

51constintCOLD_DEWS=13;//寒露

52constintHOAR_FROST_FALLS=14;//霜降

53constintWINTER_BEGINS=15;//立冬

54constintLIGHT_SNOW=16;//小雪

55constintHEAVY_SNOW=17;//大雪

56constintWINTER_SOLSTICE=18;//冬至

57constintSLIGHT_COLD=19;//小寒

58constintGREAT_COLD=20;//大寒

59constintSPRING_BEGINS=21;//立春

60constintTHE_RAINS=22;//雨水

61constintINSECTS_AWAKEN=23;//惊蛰

137voidCChineseCalendar::GetNewMoonJDs(doublejd,double*NewMoon)

138{

139for(inti=0;i

141doubleshuoJD=CalculateMoonShuoJD(jd);

142NewMoon[i]=shuoJD;

143

145}

146}

170boolCChineseCalendar::BuildAllChnMonthInfo()

171{

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

173inti;

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

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

176{

177info.mmonth=i;

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

179info.shuoJD=m_NewMoonJD[i];

180info.nextJD=m_NewMoonJD[i+1];

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

182info.leap=0;

183

184CChnMonthInfocm(&info);

185m_ChnMonthInfo.push_back(cm);

186

187yuejian++;

188}

189

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

191}

194voidCChineseCalendar::CalcLeapChnMonth()

195{

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

197

198inti;

199

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

201{

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

203i=1;

204while(i<(NEW_MOON_CALC_COUNT-1))

205{

206

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

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

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

210break;

211i++;

212}

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

214{

215m_ChnMonthInfo[i].SetLeapMonth(true);

216while(i<(NEW_MOON_CALC_COUNT-1))

217{

218m_ChnMonthInfo[i++].ReIndexMonthName();

219}

220}

221}

222}

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

图(5)演示程序的界面

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

小知识2:通式寿星公式

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

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

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

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

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

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

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

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

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

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

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:平朔和定朔

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

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

THE END
1.技术分析农历日期公式详解:如何准确计算农历日期与节气转换先战胜自己,再战胜庄家。https://www.55188.com/thread-27907839-1-1.html
2.中国农历年份,rpa,机器人,自动化至此千百年来,中国传统历——汉历(农历)所采用得干支纪年方法,与皇帝年号纪年一样以新年正月朔(元旦)为开始。 从元明清三代的史书,可见干支纪年在正月初一更替的记录:更多内容请查看https://baike.baidu.com/item/%E5%B9%B2%E6%94%AF%E7%BA%AA%E5%B9%B4/3383226 https://wdlinux.cn/html/zonghe/20241128/20015.html
3.国历和农历怎么转换6、国历与农历的换算公式 求教高人!!! 你指的是公历与农历的换算公式吧?这个算法复杂,我可以提供C或C++的API函数给你,不知道你是用什么语言来编的? 7、转换农历国历 网友分享:你好,国历1997.13,转换为农历是1997年1月7日,星星期四;国历1997.1,转换为农历是1996年12月24日,星期六。 https://www.105188.com/sh/618011.html
4.农历算法简介以及公式朔日计算公式农历算法简介以及公式 农历中天干地支的计算【C代码】 农历一百年算法(1921~2021)【C语言代码】 农历两百年算法(1901~2100)【C语言代码】 一、节气的计算 先给节气进行编号,从近日点开始的第一个节气编为0,编号如下及其相应的月份如下: 把当天和1900年1月0日(星期日)的差称为积日,那么第y年(1900年算第0年https://blog.csdn.net/ammana_babi/article/details/1375638
5.农历七七四十九算法查男女的公式准吗?怎么算男孩女孩?农历七七四十九算法查男女的公式准吗?怎么算男孩女孩? 民间一直流传着“七七四十九,问娘何月有,减去母身数,添加一十九,如单数生男,如双数生女。”的说法,但是这样计算后的数字并不能判断胎儿性别,即使有验证成功的也只是巧合。除了77计算法这一种,还有很多通过计算公式来推测胎儿性别的方式,都是没有依据的,因为人https://m.haoyunbang.cn/ll/4552.html
6.隔骨算法算男女隔骨算法准不准隔骨算法怎么算隔骨算法计算公式 隔骨和49算法哪个准 算法:有三行需要计算,第一行是截止到怀孕那个月宝爸的虚岁年龄;最后一行是截止到宝妈怀孕那个月的虚岁年龄;中间那一行是宝爸宝妈同房受孕时间的农历月份。 男方在上单岁画一整画,双岁画两半画。女方在下,单岁也是画一整画,双岁画两半画,受胎之月在中间,单月画一整画,双https://www.snsnb.com/post-144943-1.html
7.最准49算男女公式遇闰月也能算,四大正确算法比清宫图准四九算生男生女是民间的一个传言,其生男生女计算公式中,以49数字为基数保持不变,然后代入女性受孕时的农历月份和虚岁年龄,最后加上数字19得出结果数的尾数为单数,表示可能生男孩,结果尾数为双数,代表可能生女孩,下面整理有关最准49算男女公式以及4种正确算法,一起来看看吧。 https://www.born123.com/article/07aaeb89273eee139e3c.html
8.输入末次月经算生男生女的49算法公式有哪些?49算法输入末次月经算生男生女公式是:49+怀孩子时的农历月份—怀孩子时的虚岁年龄+19,如果得出的https://wenda.ayoushu.com/question/12881.html
9.输入末次月经算生男生女的49算法公式有哪些?49算法输入末次月经算生男生女公式是:49+怀孩子时的农历月份—怀孩子时的虚岁年龄+19,如果得出的结果是双数那么就会生女孩,如果得出的结果是单数,就是对应的生男孩。当然这种计算方式并没有实质性的依据,只是作为一种推测,只是给宝妈们作为一个参考,并不能完全相信。 https://www.1wuen.com/8f864901c6ac83788de4.html
10.末次月经看生男生女算法公式是什么?生男生女计算公式准吗?生男生女计算公式准吗? 在生活中,算生男生女的方法有很多,除了清宫表以外,其中末次月经看生男生女是民间流传的一种方法,又称为“四九法”,怀上宝宝的准妈妈们可以再鉴别和验证下末次月经看男女的准确率。 末次月经看生男生女算法公式是什么? 其计算公式为49+末次月经的农历月份-怀孕时的虚岁+19,如果结果是https://www.zhiyazz.com/shengzi/13283.html
11.php八字算法公式怎么用?Worktile社区要使用PHP编写八字算法公式,需要先了解八字算法的原理和计算公式。 八字算法(Bazi)是中华民族独有的一种命理学术,它使用出生年、月、日、时四个要素来推算一个人的命运。常用的八字算法公式是根据天干地支的阴阳五行相生相克的关系进行计算的。 以下是使用PHP编写八字算法公式的步骤: https://worktile.com/kb/ask/185445.html
12.二十四节气小雪是否宜婚嫁不同年份的小雪时间查询2035年小雪时间:11月22日20:02:41,农历2035年十月(大)廿三 小雪日期算法 小雪公式:(Y×D+C)-L 公式解读:Y=年数后2位,D=0.2422,L=闰年数,21世纪C=22.36,20世纪=23.08。 举例说明:2088年小雪日期=(88×0.2422+22.36)-(88÷4)=43-22=21,11月21日小雪。 https://m.smxs.com/fengshui/zhishi/138340.html
13.日柱公式是什么日柱干支推算口诀日柱,即用农历的干支代表人出生的那一天。 什么是日柱公式呢?日柱公式的用途是什么?快到华易网一起和小编了解更多关于八字日柱的内容吧。 日柱公式是什么 “日柱公式”指的是用来换算公历日期与日干支的一种历法公式。 目前,人们普遍使用的公历也就是格里历,是一种太阳历。我国过去使用的干支历也是一种太阳历,为了https://www.k366.com/bazi/193937.htm
14.闰年是怎么算的,闰年算法大揭秘世纪闰年算法是对简单闰年算法的修正。根据这个算法,能被400整除的年份也是闰年。例如,2000年是闰年,因为2000能被400整除。 公式闰年算法 公式闰年算法是一种更精确的闰年计算方法。它基于一个公式:能被4整除但不能被100整除的年份为闰年,除非能被400整除。这个公式可以用以下伪代码表示: https://www.nzw6.com/26802.html
15.wps怎么根据阳历推算农历数据分析帆软数字化转型知识库在WPS表格中,可以通过输入特定的公式来实现阳历到农历的转换。以下是一个简单的步骤: 打开WPS表格,选择一个空白单元格。 输入阳历日期,例如“2023-10-01”。 使用公式=TEXT(A1,"[$-F800]dddd")来获取该日期的农历信息。 在这个公式中,A1是你输入阳历日期的单元格。通过这个方法,用户可以快速地获得对应的农历日https://www.fanruan.com/blog/article/395936/
16.公历转农历怎么写公式?标题: 公历转农历怎么写公式? 发信站: 水木社区 (Sun Nov 19 21:00:07 2023), 站内 我看excel里面没有直接提供现成的函数,得自己手撸公转农的算法公式,这个算法是什么?如何用excel所提供的函数来写出来这个公式呢? -- 仙乡云水足生涯,摆橹横舟便是家。活剖鲜鳞烹绿鳖,旋蒸紫蟹煮红虾。 青芦笋https://www.newsmth.net/nForum/article/OfficeSoft/126142?p=1
17.十二生肖排序问卷调查显示,以立春定生肖这一传统在民间沿用和遗忘的人数各半。 当然了,若刚好出生在“争议”日期,亦可凭个人喜好去定。 出处来源:生肖的农历年算法:http://114.xixik.com/12birthpet/ 中外的生肖信仰 返回顶部 中国人的生肖信仰 生肖本是用于纪年的一套符号,是古代天文历法的一部分,后来成为了普遍被人们认同http://114.xixik.com/12birthpet/
18.公历换算农历公式.docx公历换算农历公式想要将公历转换为农历,可以根据公式:公元年数—1901(或1977)=R+4Q;那么农历日期=(1+R)+14Q+年内日期序数—(n、R、Q都是自然数,R<4)。这个公式算法对于很多数学不好的人而言是很费脑子的,算大半天也算不出来,而当今科技是比较发达的,我们想要将进行公农历转换并不需要这么复杂的计算https://m.taodocs.com/p-1021354477.html
19.命宫称骨算法东四命西四命算法公式是什么⑷ 东四命西四命算法公式是什么 东四命西四命的算法公式并不是完全统一的,而是根据男女来分别的,如果是男生的话,再计算自己是东四命和西四命的时候应用的公式是:100减去出生的年份的总数再除以9;女生的东四命西四命的计算公式为出生年份减去四的结果再除以9。 https://www.ultimate-communications.com/zh/system_405936
20.vba阴历算法51CTO博客已为您找到关于vba阴历算法的相关内容,包含IT学习相关文档代码介绍、相关教程视频课程,以及vba阴历算法问答内容。更多vba阴历算法相关解答可以来51CTO博客参与分享和学习,帮助广大IT技术人实现成长和进步。https://blog.51cto.com/topic/vbayinlisuanfa.html