简明万年历编制(C语言 )
编制万年历的要素:
农历公历对照,显示星期,农历干支年,当年生肖,国定节假日,寒天九九,暑日三伏,入梅出梅,节气时间,生辰八字等。
我编写万年历课题的内容:
一、漂亮的软件界面设计制作
二、阳历阴历对照 : 显示阴历的算法,对照,定位显示
三、加入节气节假日 : 完成像样的台历式月历显示
四、加入农历干支生肖:较完善的台历显示
五、日历式显示 :有寒天九九,暑日三伏,入梅出梅
六、生辰八字查询 :完整显示生辰八字,五星,二十八宿,十二建,五行纳音
七、节气交节时刻计算:精确时刻计算难度较高,减精度的简易算法或数据法
八、程序设计有:界面互动功能,点击日期可即时查看是日农历信息
农历算法采用数据数组方法,200年日历数据量不大。程序启动时读入即可。
数据结构18位,如daList[2000]="110010010110000205"; 前12位表示正月到腊月大小月,1为农历大月30天,0为小月29天。 第13,14位表示农历闰月,13位为农历闰月大小,14位为闰几月,
后4位表示农历年首个朔日,即俗称的正月初一的公历日期,如2月5日。
节气交节时刻计算,天文算法很精准,但太复杂,数据数组方法数据量太大,都不合适。如要求精确时间,可用数据数组方法。本程序采用曾次亮先生的算法,算法简单,但精度差些。如要精准度就采用数据数组方法,200年的数据量还可以,现在存储和内存容量都较大。我已编译了数据,需要的可索取。
台历式显示月历是公历和农历格式化打印,7天一星期打印输出。农历显示包括初一改为那个月,是节气日期改为节气名称,法定节假日显示。节假日既然是国家法定的,那就应从1949年开始显示。其实各节日哪时开始要考证,故且从权统一从1949年开始。此前也就只显示传统节日。
月历和按天日历都显示当月节气中气时间,同时显示指定查询日生辰八字。
生辰八字显示年月日六字加另列出的时辰二字。
另外还显示日八字的五行二十八宿十二建的排列字,如:甲寅 大溪水胃满 。
八字都有显示五行纳音,如:甲子 海中金 。
民间有俗称今年是金猪年金猴年。其实要看年柱的五行,如:
1984年:甲子 海中金 就是金鼠年
八字年柱月柱算法有二种,此程序采用较通用的,即年柱以立春日启算,月柱以月首节气日启算。
这里有五行纳音,二十八宿,十二建的算法。程序中有注释供同好参考。
屏幕点击可查询该日,显示各项信息,另加节假日,寒日九九,暑日三伏,入梅出梅信息。
本万年历适应用范围(1900-2100),用图形方法绘出,可加贴底图,可屏幕截图保存图片,共享图片。另外可添加图片输出和打印输出功能。贴图的图片起个文件名放在手机根目录就会自动更换。若要编制年份跨期长的万年历,可向我索取数据资料。我有(B.C.850-3000)的daList(3000)阴历数据。另外还有精确的节气时间数据 jqdata ( 3000 ) 。
下面的代码是用简单的C语言写的,很简洁,适用于初学者。我是在安卓手机上编写的,显示是手机界面。
( 代码中print...是算法测试用,这是我的测试方法,已注释掉 )
以下是源码:
//**************************************
//* 简明万年历 (1900-2100) ver. 2.5.1
//**************************************
Canvas cs;
string sBarDes[10];
int nBarId[10];
float src[4]; //ClearDraw (cls) clear screen
FileInput filebox;
string fname; //filename
int ds[3]; //get date yymmdd
int dy,dm,dd;
int wd; //weekday
int alln,alln1;
int i,k,ns,leap;
double nleap, nleapd; //农历闰月,0无闰,闰月大小
int n,n0,n1;
string s,s0,ss,s5, s6 ;
string s1,s2,s3,s4;
string s11, s12, s13, s14 ;
string wds,wdss; //weekday
float x0,y0,x1,y1;
float sx,sy;
string daList[2200] ;
//string jqdata[2200] ;
double dy0,dy1,dm1,dd1;
string dy2,dm2,dd2 ;
double hh1,mm1,ss1;
string hh2,mm2,ss2;
double jn; //jnum
string jname1,jname2;
string jqnames;
string jz60s;
double jd;
double juD,tht,yrD;
double sD; //shouD
double vs,dalt; //solar
string das0,das1,das2; // 0 last yy, 1 this yy, 2 new
double ysm,ysd; //年首月,年首日
int msd[12]; //月朔日
int msd0,msd1;
int mdx ; //农历月大小
int chuxi; //除夕在廿九
string nlms,nlds; //农历月$,农历日$
string getms,getds, mss$ ; //for print nlm$,nld$
string gzs,ggzs; //干支
int gzn;
string sxs,gsxs; //生肖
int sxn;
int jqdn,jqd1,jqd2; //print solar day ( calendar )
string jqs1,jqs2;
string jqss1,jqss2;
int gzy,gzm,gzd,gzh; //干支 yy mm dd hh
string gzys,gzms,gzds,gzhs;
int gzn1;
int yz,mz; //年柱 月柱
string bzs; //八字
string whss,g12ss,st28ss; //五行 十二建 二十八宿
int dzd0,dzd1; //冬至日
int fmn,mn,fn; //母亲节父亲节
int isdraw;
int setc; //set day color in red
string fd$ ; // fdd$ ;
string p1, p2, p3, p4, p5 ;
string mon$;
int context; //canvasProc屏幕触控
int obj;
int id;
int event; //Proc
int kx,ky, dn, dln ;
main(){
setTitle ("简明月历 (1900-2100)");
jqnames="小寒大寒立春雨水惊蛰春分清明谷雨立夏小满芒种夏至小暑大暑立秋处暑白露秋分寒露霜降立冬小雪大雪冬至";
nlds="初一初二初三初四初五初六初七初八初九初十十一十二十三十四十五十六十七十八十九二十廿一廿二廿三廿四廿五廿六廿七廿八廿九三十初一初二初三";
wdss="星期日星期一星期二星期三星期四星期五星期六";
nlms="冬月腊月正月二月三月四月五月六月七月八月九月十月冬月腊月";
gzs="甲子乙丑丙寅丁卯戊辰己巳庚午辛未壬申癸酉甲戌乙亥丙子丁丑戊寅己卯庚辰辛己壬午癸未甲申乙酉丙戌丁亥戊子己丑庚寅辛卯壬辰癸巳甲午乙未丙申丁酉戊戌己亥庚子辛丑壬寅癸卯甲辰乙巳丙午丁未戊申己酉庚戌辛亥壬子癸丑甲寅乙卯丙辰丁巳戊午己未庚申辛酉壬戌癸亥";
sxs="鼠牛虎兔龙蛇马羊猴鸡狗猪";
whss="海中金炉中火大林木路旁土剑锋金山头火洞下水城墙土白腊金杨柳木泉中水屋上土霹雷火松柏木长流水沙中金山下火平地木壁上土金箔金佛灯火天河水大驿土钗钏金桑松木大溪水沙中土天上火石榴木大海水";
g12ss="建除满平定执破危成收开闭";
st28ss="角亢氐房心尾箕斗牛女虚危室壁奎娄胃昴毕觜参井鬼柳星张翼轸";
//cs.SetBackground(200,250,200);
setDisplay (1);
cs.Active ();
sBarDes[0]="输入日期";
nBarId[0]=100;
sBarDes[1]="显示月历";
nBarId[1]=101;
sBarDes[2]="< 上一月 ";
nBarId[2]=102;
sBarDes[3]="下一月 > ";
nBarId[3]=103;
sBarDes[4]="退出程序";
nBarId[4]=104;
sBarDes[5]=" ";
nBarId[5]=105;
setToolBarHeight(10);
setButtonTextSize(13);
setToolBarBackgroundColor(255,250,250,250);
setButtonColor(255,240,240,240);
setButtonTextColor(255,0,0,220);
setToolBar(100,myToolBarProc,sBarDes,nBarId,6);
cs.SetProc (context, mycanvasProc); //触控
readDat (); //read calendar data 1900-2100
isdraw=0;
fname="/storage/emulated/0/jiac.jpg";
cs.DrawBitmap(fname,0,2); //加底图
showVer () ;
getDate(ds); //getDate = today
dy=ds[0]; dm=ds[1]; dd=ds[2];
getWeekday();
calendar(); //show calendar at start
cs.SetTextSize (60);
ss="Welcome you ...... ! " ;
cs.SetColor(205,250,150,0);
cs.DrawText (ss, 35, 100);
cs.Update () ;
while (){}
}//main ()
showVer (){ //启动页
cs.SetTextStyle (1);
cs.SetFillMode(1);
cs.SetColor(50,220,220,20);
cs.DrawRect (0,940,720,1030);
cs.DrawRect (540,30,716,400);
cs.SetTextSize (66);
ss="萬年历" ;
cs.SetColor(205,0,100,180);
cs.DrawText (ss, 35, 985);
cs.SetColor(205,180,250,250);
cs.DrawText (ss, 30, 980);
cs.SetFillMode(0);
cs.SetColor(205,250,130,0);
cs.DrawText (ss, 30, 980);
cs.SetTextStyle (0);
cs.SetFillMode(1);
cs.SetTextSize (26);
s="编译人:张纯叔 ([email protected]) ";
cs.DrawText(s,30,1020);
cs.DrawText("Version 2.5.1",460,1020);
cs.Update ();
}//showVer ()
mycanvasProc (int context,int obj,int id,int event,float x,float y){
dln=dln+1 ; //触控:减少屏幕闪烁
if ((dln-dln/3*3)==0){ goto isdo ; }
return ;
//*******
isdo :
cs.SetFillMode (1);//0不填色,1填色
if (x>45&&x<520&&y>260&&y<720){
kx=(int)((x+40)/70)*70; //日历区位取整数
ky=(int)((y-265)/80)*80;
kx=kx/70;
ky=ky/80;
dn=(ky)*7+kx-wd; //选定日期 dn
if (dn<1) dn=1 ; //dn=the first day
if (dn>ns) dn=dd ; //dn=today
}
dd=dn; //click to chose this day
getWeekday () ;
calendar() ; //renew the day
}//mycanvasProc ()
inputDate (){ //日期输入
string sDat[101];
getDate(ds); //getDate = today
pickDate("输入日期:",ds); //input date
clearOutput ();
//print ds[0],ds[1],ds[2];
dy=ds[0];
dm=ds[1];
dd=ds[2];
print "InputDate = ",dy ,"-",dm,"-",dd;
dd2=intToString(dd); //this day $
getWeekday () ;
}//inputDate()
getWeekday (){//计算月首日星期几
int ty;
int tm;
clearOutput ();
ty=dy;
tm=dm;
if (dm<3){
ty=dy-1;
tm=dm+12; }
//first day=1 this month
//iWeek=(d+2*m+3*(m+1)/5+y+y/4-y/100+y/400)
//mod 7 基姆拉尔森公式
alln=2*tm+3*(tm+1)/5+ty+(int)(ty/4);
alln=alln-(int)(ty/100)+(int)(ty/400)+2;
wd=alln-alln/7*7; //mod (alln,7)
wds=subString(wdss,wd*3,3);
string yds; //for gz day wh 28star 12jian
string ydds;
double tms;
yds="000031059090120151181212243273304334";
ydds=subString(yds,(dm-1)*3,3);
tms=stringToDouble(ydds);
alln1=(dy-1900)*365+((dy-1900-1)/4)+(int)(tms)+1;
if ((dy-dy/4*4)==0&&dm>2)alln1=alln1+1;
print "all days = ",alln," ",alln1;
// return weekday = wds $
}//getWeekday ()
calnlds(){ //计算农历要素
//calculate 农历月$ getms 农历日$ getds*******
//double nleap,nleapd; //农历闰月,0无闰,闰月大小
s=daList[dy-1];
das0=s;
print "last year = ",dy-1;
print "last year das0 = ", das0;
s=daList[dy];
das1=s;
print "this year = ",dy;
print "this year das1 = ",das1;
s=subString(das1,15,1);
ysm=stringToDouble(s);
print "年首月 = ",(int)(ysm);
s=subString(das1,16,2);
ysd=stringToDouble(s);
print "月首日 = ",(int)(ysd);
s=subString(das1,13,1);
if (s=="a") s="10" ;
nleap=stringToDouble (s);
n=(int)(nleap);
s=subString(das1,12,1);
nleapd=stringToDouble (s) ;
nleapd=(int)nleapd ;
print "nleap = ", n," nleapd = ",nleapd;
if(nleap==0){
ss=subString (das0,10,2)+subString (das1,0,12);
}else {ss=subString(das0,11,1)+subString(das1,0,n)+subString(das1,12,1)+subString(das1,n,12-n);}
if (dy==1919) ss="11010010011011" ;
if (dy==1984) ss="11101100100101" ;
if (dy==2052) ss="11010010010111" ;
das2=ss; //纠正偏差
print "new das2 = ",das2;
print " ";
//**** calculate msd(12) // 年 月朔日$
n0=(int)(ysd); //年首日起算
if (dy-(int)(dy/4)*4==0){leap=1;}else{leap=0;}
//print "leap = ",leap;
if (ysm==1){
s=subString(das2,1,1);
if (s=="1"){n=30;}else{n=29;}
msd[1]=n0;
msd[2]=msd[1]+n-31; }
if (ysm==2){
s=subString(das2,1,1);
if (s=="1"){n=30;}else{n=29;}
msd[1]=31+n0-n;
msd[2]=n0; }
s=subString(das2,2,1);
if (s=="1"){n=30;}else{n=