基于MATLAB的万年历计算
黄小川(200431610102)
测绘工程专业2004级9班
摘要:运用MATLAB编程实现1936—2032年农历与公历间的相互转换,并求当日是星期几。
关键词:万年历 公历转化为农历 农历转化为公历 求当天是星期几
正文:
1. 概述:知道公历年月日求农历日期,知道农历年月日求公历日期,并求当日是星期几。
2. 相关知识及原理:
公历:公历是现在国际通用的历法,又称格列历,通称阳历。公历将一年分为十二个月,其中一、三、五、七、八、十、十二月有31天,俗称“大月”;四、六、九、十一月有30天;平年二月有28天,闰年二月有29天,这样公历闰年一年有366天,平年有365天。
公历闰年:若一年年数不能被4整除,或能被100整除但不能被400整除,则称这一年为平年,否则为闰年。
农历:农历是基于对地球公转和月相变化的观测的。我国现采用的农历结合了阳历与阴历(伊斯兰历)的记年方法:一年有十二个月,其中6个大月(30天),6个小月(29天),一个农历年有354天。
农历闰月:为了平衡公里年与农历年的天数差别,农历采用在适当时候设立闰月的方法,一般三年左右设一闰月,闰月可以是大月,也可以是小月。具体设置原则由节气而定,方法较为复杂。
公历与农历间的转换:公历是纯数学的记年法,而农历是基于观测结果之上的。两者见的转换比较复杂,无法用简单的数学公式表示。因此,这里采用的方法是首先查得1936年至2032年相关的资料,包括:该年农历大年初一到公历元旦的天数、该年农历各月的天数、该年农历有无闰月以及在何处闰月。这样在公历化为农历时,只需算得改日距该年农历大年初一的天数,对应该年农历各月的天数,即可得到农历的月份,及该日在该农历月是第几天;在农历化为公历时,同样,需算得该日距该年元旦的天数,通过类似转化,即可求得公历日期。
求星期数:已知公历求星期数时,计算出改日距一特定日期的天数,则该日星期数=特定日期星期数+距离天数除以7的余数;已知农历时,只需将农历转换为公历,再由公历日期求星期数即可。
3. 实例计算:
3.1数据说明:
runyear %1936到该年的闰年数
gongli_year %公历年数
gongli_mongth %公历月数
gongli_day %公历日期
gongli_sumofdays %公历各月累积天数
gongli_daysofyear %该日是该公历年的第几天
nongli_year %农历年数
nongli_month %农历月数
nongli_day %农历日期
nongli_sumofdays %农历各月累积天数
nongli_daysofyear %该日是该农历年的第几天
3.2MATLAB源程序:
%getdayofweek.m
%由公历日期求星期数
runyear=floor((gongli_year-1933)/4); %到1936年的闰年数
weekday=rem((gongli_year-1936-runyear)*365+runyear*366
+gongli_sumofdays(gongli_month)+gongli_day,7)+1; %求星期数
weekdayoutput=['二','三','四','五','六','日','一'];
fprintf('这一天是星期%s,',weekdayoutput(weekday))
%gongli_input
%输入公历日期
gongli_year=input('请输入一公历个年份:');
while (gongli_year-1936)*(gongli_year-2032)>0; %输入年份不符合要求
gongli_year=input('猪头!年份应在1936至2032之间,请再输一次:');
end
gongli_month=input('请输入一个公历月份:');
while (gongli_month-1)*(gongli_month-12)>0 %输入月份不符合要求
gongli_month=input('猪头!月份应在1至12之间,请再输一次:');
end
sign=0; %判断是否是闰年
if rem(gongli_year,4)==0
sign=sign+1;
end
if sign==1
gongli_sumofdays=[0,31,60,91,121,152,182,213,244,274,305,335,366];
else
gongli_sumofdays=[0,31,59,90,120,151,181,212,243,273,304,334,365];
end
gongli_day=input('请输入一个公历日期:');
while (gongli_day-1)*(gongli_day-(gongli_sumofdays(gongli_month+1)
-gongli_sumofdays(gongli_month)))>0
gongli_day=input('猪头!这个月没有这个日期,请再输一次:');
end
%gongli2gongli.m
%将公历日期转化为农历日期
gongli_daysofyear=gongli_sumofdays(gongli_month)+gongli_day;
%求该日是当公历年的第几天
if gongli_daysofyear
%该日农历年数比公历年数少一
nongli_year=gongli_year-1;
if rem(gongli_year-1,4)==0
nongli_daysofyear=366+gongli_daysofyear-wannianli_matrix(nongli_year-1935,1);
else nongli_daysofyear=365+gongli_daysofyear-wannianli_matrix(nongli_year-1935,1);
end
else nongli_year=gongli_year;
%该日农历年数与公历年数相同
nongli_daysofyear=gongli_daysofyear-wannianli_matrix(nongli_year-1935,1);
end
nongli_sumofdays=0;nongli_month=3;
while nongli_daysofyear-1>nongli_sumofdays
nongli_sumofdays=nongli_sumofdays+wannianli_matrix(nongli_year-1935,nongli_month);
nongli_month=nongli_month+1;
end
nongli_day=nongli_daysofyear-(nongli_sumofdays-wannianli_matrix(nongli_year-1935,nongli_month-1));
nongli_month=nongli_month-3;
nongli_tiangan=['庚','辛','壬','癸','甲','乙','丙','丁','戊','已'];
nongli_dizhi=['申','酉','戌','亥','子','丑','寅','卯','辰','巳','午','未'];
if wannianli_matrix(nongli_year-1935,2)~=0&nongli_month>wannianli_matrix(nongli_year-1935,2)
nongli_month=nongli_month-1;
if nongli_month==wannianli_matrix(nongli_year-1935,2)
fprintf('农历%s%s年闰%1.0f月%1.0f日。\n',nongli_tiangan(rem(nongli_year,5)+1),nongli_dizhi(rem(nongli_year,12)+1),nongli_month,nongli_day)
else fprintf('农历%s%s年%1.0f月%1.0f日。\n',nongli_tiangan(rem(nongli_year,5)+1),nongli_dizhi(rem(nongli_year,12)+1),nongli_month,nongli_day)
end
else fprintf('农历%s%s年%1.0f月%1.0f日。\n',nongli_tiangan(rem(nongli_year,5)+1),nongli_dizhi(rem(nongli_year,12)+1),nongli_month,nongli_day)
end
%nongli_input
%输入农历日期
nongli_year=input('请输入一个农历年份:');
while (nongli_year-1936)*(nongli_year-2031)>0; %输入年份不符合要求
nongli_year=input('猪头!年份应在1936至2031之间,请再输一次:');
end
nongli_month=input('请输入一个农历月份:');
while (nongli_month-1)*(nongli_month-12)>0%输入月份不符合要求
nongli_month=input('猪头!月份应在1至12之间,请再输一次:');
end
if wannianli_matrix(nongli_year-1935,2)==nongli_month %输入月份和当年闰月相同
answer=input('是闰月吗?(y/n):','s'); %判断是否为闰月
while answer~='y'&answer~='n'
answer=input('到底是不是啊?(y/n):','s');
end
if answer=='y'
nongli_month=nongli_month+1;
end
elseif wannianli_matrix(nongli_year-1935,2)~=0&wannianli_matrix(nongli_year-1935,2)~=nongli_month
if nongli_month>wannianli_matrix(nongli_year-1935,2)
nongli_month=nongli_month+1;
end
end
nongli_day=input('请输入一个农历日期:');
while (nongli_day-1)*(nongli_day-wannianli_matrix(nongli_year-1935,nongli_month+2))>0
nongli_day=input('猪头!这个月没有这个日期,请再输一次:');
end
sign=0;
if rem(nongli_year,4)==0
sign=sign+1;
end
if sign==1
gongli_sumofdays=[0,31,60,91,121,152,182,213,244,274,305,335,366];
else
gongli_sumofdays=[0,31,59,90,120,151,181,212,243,273,304,334,365];
end
gongli_year=nongli_year;
%nongli2gongli
%将农历日期转化为公历日期
nongli_daysofyear=nongli_day; %求该日是当农历年的第几天
if nongli_month~=1
for k=1:nongli_month-1
nongli_daysofyear=nongli_daysofyear+wannianli_matrix(nongli_year-1935,k+2);
end
end
gongli_daysofyear=nongli_daysofyear+wannianli_matrix(nongli_year-1935,1);
if gongli_daysofyear>gongli_sumofdays(13) %该日公历年数比农历年数多一
gongli_daysofyear=gongli_daysofyear-gongli_sumofdays(13);
gongli_year=nongli_year+1;
end
gongli_month=1;
while gongli_daysofyear-1>gongli_sumofdays(gongli_month)
gongli_month=gongli_month+1;
end
gongli_month=gongli_month-1;
gongli_day=gongli_daysofyear-gongli_sumofdays(gongli_month);
getdayofweek
fprintf('%1.0f年%1.0f月%1.0f日',gongli_year,gongli_month,gongli_day)
%wannianli.m
%主程序
wannianli_matrix=[23, 3, 30, 29, 29, 30, 29, 29, 30, 30, 29, 30, 30, 30, 29, 384
41, 0, 30, 29, 29, 30, 29, 29, 30, 29, 30, 30, 30, 29, 0, 354
30, 7, 30, 30, 29, 29, 30, 29, 29, 30, 29, 30, 30, 29, 30, 384
49, 0, 30, 30, 29, 29, 30, 29, 29, 30, 29, 30, 29, 30, 0, 354
38, 0, 30, 30, 29, 30, 29, 30, 29, 29, 30, 29, 30, 29, 0, 354
26, 6, 30, 30, 29, 30, 30, 29, 30, 29, 29, 30, 29, 30, 29, 384
45, 0, 30, 29, 30, 30, 29, 30, 29, 30, 29, 30, 29, 30, 0, 355
35, 0, 29, 30, 29, 30, 29, 30, 30, 29, 30, 29, 30, 29, 0, 354
24, 4, 30, 29, 30, 29, 30, 29, 30, 29, 30, 30, 29, 30, 30, 385
43, 0, 29, 29, 30, 29, 29, 30, 29, 30, 30, 30, 29, 30, 0, 354
32, 0, 30, 29, 29, 30, 29, 29, 30, 29, 30, 30, 29, 30, 0, 354
21, 2, 30, 30, 29, 29, 30, 29, 29, 30, 29, 30, 29, 30, 30, 384
40, 0, 30, 29, 30, 29, 30, 29, 29, 30, 29, 30, 29, 30, 0, 354
28, 7, 30, 29, 30, 30, 29, 30, 29, 29, 30, 29, 30, 29, 30, 384
47, 0, 29, 30, 30, 29, 30, 30, 29, 29, 30, 29, 30, 29, 0, 354
36, 0, 30, 29, 30, 30, 29, 30, 29, 30, 29, 30, 29, 30, 0, 355
26, 5, 29, 30, 29, 30, 29, 30, 29, 30, 30, 29, 30, 29, 30, 384
44, 0, 29, 30, 29, 29, 30, 30, 29, 30, 30, 29, 30, 29, 0, 354
33, 0, 30, 29, 30, 29, 29, 30, 29, 30, 30, 29, 30, 30, 0, 355
23, 3, 29, 30, 29, 30, 29, 29, 30, 29, 30, 29, 30, 30, 30, 384
42, 0, 29, 30, 29, 30, 29, 29, 30, 29, 30, 29, 30, 30, 0, 354
30, 8, 30, 29, 30, 29, 30, 29, 29, 30, 29, 30, 29, 30, 29, 383
48, 0, 30, 30, 30, 29, 30, 29, 29, 30, 29, 30, 29, 30, 0, 355
38, 0, 29, 30, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 0, 354
27, 6, 30, 29, 30, 29, 30, 30, 29, 30, 29, 30, 29, 30, 29, 384
45, 0, 30, 29, 30, 29, 30, 29, 30, 30, 29, 30, 29, 30, 0, 355
35, 0, 29, 30, 29, 29, 30, 29, 30, 30, 29, 30, 30, 29, 0, 354
24, 4, 30, 29, 30, 29, 29, 30, 29, 30, 29, 30, 30, 30, 29, 384
43, 0, 30, 29, 30, 29, 29, 30, 29, 30, 29, 30, 30, 30, 0, 355
32, 0, 29, 30, 29, 30, 29, 29, 30, 29, 29, 30, 30, 29, 0, 353
20, 3, 30, 30, 30, 29, 30, 29, 29, 30, 29, 29, 30, 30, 29, 384
39, 0, 30, 30, 29, 30, 30, 29, 29, 30, 29, 30, 29, 30, 0, 355
29, 7, 29, 30, 29, 30, 30, 29, 30, 29, 30, 29, 30, 29, 30, 384
47, 0, 29, 30, 29, 30, 29, 30, 30, 29, 30, 29, 30, 29, 0, 354
36, 0, 30, 29, 29, 30, 29, 30, 30, 29, 30, 30, 29, 30, 0, 355
26, 5, 29, 30, 29, 29, 30, 29, 30, 29, 30, 30, 30, 29, 30, 384
45, 0, 29, 30, 29, 29, 30, 29, 30, 29, 30, 30, 29, 30, 0, 354
33, 0, 30, 29, 30, 29, 29, 30, 29, 29, 30, 30, 29, 30, 0, 354
22, 4, 30, 30, 29, 30, 29, 29, 30, 29, 29, 30, 30, 29, 30, 384
41, 0, 30, 30, 29, 30, 29, 29, 30, 29, 29, 30, 29, 30, 0, 354
30, 8, 30, 30, 29, 30, 29, 30, 29, 30, 29, 29, 30, 29, 30, 384
48, 0, 30, 29, 30, 30, 29, 30, 29, 30, 29, 30, 29, 29, 0, 354
37, 0, 30, 29, 30, 30, 29, 30, 30, 29, 30, 29, 30, 29, 0, 355
27, 6, 30, 29, 29, 30, 29, 30, 30, 29, 30, 30, 29, 30, 29, 384
46, 0, 30, 29, 29, 30, 29, 30, 29, 30, 30, 29, 30, 30, 0, 355
35, 0, 29, 30, 29, 29, 30, 29, 29, 30, 30, 29, 30, 30, 0, 354
24, 4, 30, 29, 30, 29, 29, 30, 29, 29, 30, 29, 30, 30, 30, 384
43, 0, 30, 29, 30, 29, 29, 30, 29, 29, 30, 29, 30, 30, 0, 354
32, 10, 30, 29, 30, 30, 29, 29, 30, 29, 29, 30, 29, 30, 30, 384
50, 0, 29, 30, 30, 29, 30, 29, 30, 29, 29, 30, 29, 30, 0, 354
39, 0, 29, 30, 30, 29, 30, 30, 29, 30, 29, 30, 29, 29, 0, 354
28, 6, 30, 29, 30, 29, 30, 30, 29, 30, 30, 29, 30, 29, 29, 384
47, 0, 30, 29, 30, 29, 30, 29, 30, 30, 29, 30, 30, 29, 0, 355
36, 0, 30, 29, 29, 30, 29, 29, 30, 30, 29, 30, 30, 30, 0, 355
26, 5, 29, 30, 29, 29, 30, 29, 29, 30, 29, 30, 30, 30, 30, 384
45, 0, 29, 30, 29, 29, 30, 29, 29, 30, 29, 30, 30, 30, 0, 354
34, 0, 29, 30, 30, 29, 29, 30, 29, 29, 30, 29, 30, 30, 0, 354
22, 3, 29, 30, 30, 29, 30, 29, 30, 29, 29, 30, 29, 30, 29, 383
40, 0, 30, 30, 30, 29, 30, 29, 30, 29, 29, 30, 29, 30, 0, 355
30, 8, 29, 30, 30, 29, 30, 29, 30, 30, 29, 29, 30, 29, 30, 384
49, 0, 29, 30, 29, 30, 30, 29, 30, 29, 30, 30, 29, 29, 0, 354
37, 0, 30, 29, 30, 29, 30, 29, 30, 30, 29, 30, 30, 29, 0, 355
27, 5, 30, 29, 29, 30, 29, 29, 30, 30, 29, 30, 30, 29, 30, 384
46, 0, 30, 29, 29, 30, 29, 29, 30, 29, 30, 30, 30, 29, 0, 354
35, 0, 30, 30, 29, 29, 30, 29, 29, 30, 29, 30, 30, 29, 0, 354
23, 4, 30, 30, 29, 30, 29, 30, 29, 29, 30, 29, 30, 29, 30, 384
42, 0, 30, 30, 29, 30, 29, 30, 29, 29, 30, 29, 30, 29, 0, 354
31, 0, 30, 30, 29, 30, 30, 29, 30, 29, 29, 30, 29, 30, 0, 355
21, 2, 29, 30, 29, 30, 30, 29, 30, 29, 30, 29, 30, 29, 30, 384
39, 0, 29, 30, 29, 30, 29, 30, 30, 29, 30, 29, 30, 29, 0, 354
28, 7, 30, 29, 30, 29, 30, 29, 30, 29, 30, 30, 29, 30, 30, 385
48, 0, 29, 29, 30, 29, 29, 30, 29, 30, 30, 30, 29, 30, 0, 354
37, 0, 30, 29, 29, 30, 29, 29, 30, 29, 30, 30, 29, 30, 0, 354
25, 5, 30, 30, 29, 29, 30, 29, 29, 30, 29, 30, 29, 30, 30, 384
44, 0, 30, 29, 30, 29, 30, 29, 29, 30, 29, 30, 29, 30, 0, 354
33, 0, 30, 29, 30, 30, 29, 30, 29, 29, 30, 29, 30, 29, 0, 354
22, 4, 30, 29, 30, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 384
40, 0, 30, 29, 30, 30, 29, 30, 29, 30, 29, 30, 29, 30, 0, 355
30, 9, 29, 30, 29, 30, 29, 30, 29, 30, 30, 29, 30, 29, 30, 384
49, 0, 29, 30, 29, 29, 30, 29, 30, 30, 30, 29, 30, 29, 0, 354
38, 0, 30, 29, 30, 29, 29, 30, 29, 30, 30, 29, 30, 30, 0, 355
27, 6, 29, 30, 29, 30, 29, 29, 30, 29, 30, 29, 30, 30, 30, 384
46, 0, 29, 30, 29, 30, 29, 29, 30, 29, 30, 29, 30, 30, 0, 354
35, 0, 29, 30, 30, 29, 30, 29, 29, 30, 29, 29, 30, 30, 0, 354
24, 4, 29, 30, 30, 30, 29, 30, 29, 29, 30, 29, 30, 29, 30, 384
42, 0, 29, 30, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 0, 354
31, 0, 30, 29, 30, 29, 30, 30, 29, 30, 29, 30, 29, 30, 0, 355
21, 2, 29, 30, 29, 30, 29, 30, 29, 30, 30, 29, 30, 29, 30, 384
40, 0, 29, 30, 29, 29, 30, 29, 30, 30, 29, 30, 30, 29, 0, 354
28, 6, 30, 29, 30, 29, 29, 30, 29, 30, 29, 30, 30, 30, 29, 384
47, 0, 30, 29, 30, 29, 29, 30, 29, 29, 30, 30, 30, 29, 0, 354
36, 0, 30, 30, 29, 30, 29, 29, 30, 29, 29, 30, 30, 29, 0, 354
25, 5, 30, 30, 30, 29, 30, 29, 29, 30, 29, 29, 30, 30, 29, 384
43, 0, 30, 30, 29, 30, 29, 30, 29, 30, 29, 29, 30, 29, 0, 354
32, 0, 30, 30, 29, 30, 30, 29, 30, 29, 30, 29, 30, 29, 0, 355
22, 3, 29, 30, 30, 29, 30, 29, 30, 30, 29, 30, 29, 30, 29, 384];
%根据天文观测得到的参数矩阵,每一行为一年(1936-2032)
%第一列为当年公历元旦距农历春节的天数
%第二列为当年在哪一个月闰月,若为0则没有闰月
%第三到十五列为每个月的天数(闰月在所闰月的后面)
%第十六列为该年天数(本次编程没有用到)
s=input('请选择你要进行的计算(1/2):1.由公历算农历2.又农历算公历\n');
while s~=1&s~=2
s=input('猪头!请选择1或2,再输入一次:')
end
switch s
case 1
gongli_input
getdayofweek
gongli2nongli
case 2
nongli_input
nongli2gongli
end
3.3结果输出:
4.结论与讨论:
经过多次实验,本程序进行公农历转化和求星期数的结果基本上符合事实,但在个别日期上会出错,比如1932和2032年附近靠近边界的日期、农历闰月的日期等。
可以加以改进的地方:
1.从农历产生的根源入手,探讨地、月球的运动,计算农历计年的规律,从而无限扩大查询日期的范围。
2.实现可视化和交互式界面,以日历方式输出。
3.加如节日和农历节气的显示。
参考文献
1. 对公历和农历的认识参考百度网www.baidu.com
2. 程序的部分思想及观测矩阵wannianli_matrix参考CSDN社区
http://topic.csdn.net/t/20030106/16/1331826.html