时间: 2021-07-31 作者:daque
抱雪 你到过我的网页吗?在我的网页上有如许一个场合: 你提防到了吗,在表露功夫的场合除去表露公历除外,还表露了旧历:旧历辛已(蛇)年仲春廿三日未时,比普遍的网站上只表露公历就酷多了(如何像大吹大擂?其余网站万万别去告我违犯了告白法)。这是如何做的呢?本来很大略,只有一个小小的php大概javascript步调就不妨了。 你不要焦躁地问我要php或js的步调,最要害的是要领会算法,即使你领会了变换的原因,就不妨到达伟人所说的:举一而三反焉,到时尽管是用php、delphi、js仍旧jsp、vb,你都不妨很快地写公历旧历彼此变换的步调来出来。我牢记有高人已经说过,编制程序谈话不过东西,数据构造才是最要害的,此话诚不虚也。 谈天少说,底下我就来引见一下简直的算法。 开始是要生存公旧历之间的变换消息:以大肆一年动作开始,把从这一年起几何年(几何是几何?就看你的须要了)的旧历消息生存起来(在我的vcl中,是以1921年动作开始)。回顾一下,咱们凡是是还好吗来变换公历旧历的呢?是查万日历,万日历有每一天的公历旧历,径直一查就不妨了。那么咱们可不不妨也如许做呢?固然不妨,然而,如许做就要收录每一天的消息,处事量就会很大,以是咱们要简化那些消息。如何简化呢?要生存一年的消息本来只有两个消息就不妨了:1、旧历每个月的巨细;2、本年能否有闰月,闰几月以及闰月的巨细。用一个平头来生存那些消息就充满了。简直的本领是:用一位来表白一个月的巨细,大月记为1,小建记为0,如许就用掉12位(无闰月)或13位(有闰月),再用高4位来表白闰月的月份,没有闰月记为0。比方说,2000年的消息数据是是0xc96,化成二进制即是110010010110b,表白的含意是指1、2、5、8、10、11月大,其他月小;2001年的旧历消息数据是0x41a95,个中4表白本年闰四月份,月份巨细消息即是0x1a95(由于闰月,以是有13位),简直的即是1、2、4、5、8、10、12月大,其他月份小(0x1a95=1101010010101b),要提防在四月份的反面那一个0表白的是闰四月份小,接着的谁人1表白5月大。如许就不妨用一个数组来生存那些消息。在我的vcl步调中是用chinesecalendardata[]这个数组来生存那些消息。 为了简单对算法的领会,开始来看看我的vcl组件hsdivinecalendar的头文献 //--------------------------------------------------------------------------- #ifndef hsdivinecalendarh #define hsdivinecalendarh #define allyears 100 //设置变换的年数:100年 //--------------------------------------------------------------------------- #include <sysutils.hpp> #include <controls.hpp> #include <classes.hpp> #include <forms.hpp> //--------------------------------------------------------------------------- class package thsdivinecalendar : public tcomponent { private: int chinesecalendardata[allyears]; //旧历数据 ansistring str2,num; //要用的字符串 void __fastcall c2e(); //旧历到公历 void __fastcall e2c(); //公历到旧历 tdatetime thedate; //日子 int fyear,fmonth,fday,ftime; //公积年月日时 int fcyear,fcmonth,fcday,fctime; //农积年月日时 ansistring __fastcall getdatestring(); //获得日子字符串 ansistring __fastcall getcdatestring(); //获得旧历日子字符串 int __fastcall getbit(int m,int n); //获得1bit void __fastcall getymd(); //获得岁月日 void __fastcall setdate(tdatetime); //用一个tdatetime典型的变量变换 //-----------辨别窜改公历的岁月日时------------------------------------- void __fastcall setyear(int ayear){setby(ayear,fmonth,fday,ftime);}; void __fastcall setmonth(int amonth){setby(fyear,amonth,fday,ftime);}; void __fastcall setday(int aday){setby(fyear,fmonth,aday,ftime);}; void __fastcall settime(int atime){setby(fyear,fmonth,fday,atime);}; //-----------辨别窜改旧历的岁月日时--------------------------------------- void __fastcall setcyear(int acyear){setbyc(acyear,fcmonth,fcday,fctime);}; void __fastcall setcmonth(int acmonth){setbyc(fcyear,acmonth,fcday,fctime);}; void __fastcall setcday(int acday){setbyc(fcyear,fcmonth,acday,fctime);}; void __fastcall setctime(int actime){setbyc(fcyear,fcmonth,fcday,actime);}; tdatetime __fastcall getlastjie(); //博得上一个节 tdatetime __fastcall getnextjie(); //博得下一个节 tdatetime __fastcall getlastqi(); //博得上一其中气 tdatetime __fastcall getnextqi(); //博得下一其中气 int __fastcall getdayofweek(); //博得一周的第几天 ansistring __fastcall getweekstring(); //归来礼拜几的字符串 protected: public: void __fastcall setby(int,int,int,int); //用公历树立 void __fastcall setbyc(int,int,int,int); //用旧历树立 __fastcall thsdivinecalendar(tcomponent* owner); //属性:岁月日时 __property int year={read=fyear,write=setyear}; __property int month={read=fmonth,write=setmonth}; __property int day={read=fday,write=setday}; __property int time={read=ftime,write=settime}; //属性:农积年月日时 __property int cyear={read=fcyear,write=setcyear}; __property int cmonth={read=fcmonth,write=setcmonth}; __property int cday={read=fcday,write=setcday}; __property int ctime={read=fctime,write=setctime}; //公历旧历日子字符串 __property ansistring datestring={read=getdatestring}; __property ansistring cdatestring={read=getcdatestring}; //其余属性 __property tdatetime datetime={read=thedate,write=setdate}; __property tdatetime lastjie = { read=getlastjie }; __property tdatetime nextjie = { read=getnextjie }; __property tdatetime lastqi = { read=getlastqi }; __property tdatetime nextqi = { read=getnextqi }; __property int dayofweek = { read=getdayofweek }; __property ansistring weekstring = { read=getweekstring }; __published: }; //--------------------------------------------------------------------------- #endif 底下引见变换的简直算法。 一、公历变换成旧历 1、计划出所求功夫到开始年一月月朔的天数。 2、从开始年份发端,减去每一月的天数,从来到结余天数没有下一个月多为止 此时,chinesecalendardata[]的下标到了几何,即是减去了几何年,用开始年份加上这个下标就不妨获得农积年份;而后看减去了几个月,即使今年不闰月大概闰月还在反面,就不妨径直获得旧历月份,即使在闰月月份数反面一个月,则这个月即是闰月,即使在闰月的反面,则要减去1本领获得月份数;结余的天数即是旧历日;旧历时用(公历时+1)/2就不妨大略地获得了。简直的代码如次: //--------------------------------------------------------------------------- void __fastcall thsdivinecalendar::e2c() { int total,m,n,k; bool isend=false; //用以确定能否不够减了 total=(int)thedate-7709; //到1921-2-8(一月月朔)的天数 for(m=0;;m++) { /*确定今年能否闰月,用以决定月份消息的开始 有闰月有13位(0~12),无12位(0~11)*/ k=(chinesecalendardata[m]<0xfff)?11:12; for(n=k;n>=0;n--) { //即使不够减 if(total<=29+getbit(chinesecalendardata[m],n)) { isend=true; //树立标记 break; //退出内层轮回 } /*够减,减去一个月的天数 先减去29天即使月大,则对应的消息位为1, 又减去一天*/ total=total-29-getbit(chinesecalendardata[m],n); } if(isend)break; //即使不够减,退出外层轮回 } fcyear=1921 + m; //农积年=开始年份+下标 fcmonth=k-n+1; //旧历月=今年的月份数(k+1)减去仍旧减去的月份数(n) fcday=total; //旧历日=结余天数 unsigned short int t1,t2,t3,t4; thedate.decodetime(&t1,&t2,&t3,&t4); fctime=(t1+1)>>1; //旧历时 if(k==12) //即使今年有闰月 { if(fcmonth==chinesecalendardata[m]/0x10000+1)//即是闰月 fcmonth=1-fcmonth; if(fcmonth>chinesecalendardata[m]/0x10000+1)//闰月反面 fcmonth--; } } //---------------------------------------------------------------------------- 二、旧历到公历的变换 这个算法比拟大略,只有计划所求功夫到开始年一月月朔的总天数就不妨了,要计划总天数,只有统计出本月往日的大月小建书就不妨了,而后把这个值付与tdatetime典型的thedate就不妨用tdatetime的分子因变量decodedate获得公历的岁月日了。简直代码如次: //---------------------------------------------------------------------------- void __fastcall thsdivinecalendar::c2e() { int i,k,m,p,y[]={0,0}; //y[0]:小建、y[1]:大月 //今年往日的大月小建数 for(i=0;i<fcyear-1921;i++) { k=(chinesecalendardata[i]<0xfff)?11:12; for(m=0;m<=k;m++) y[getbit(chinesecalendardata[i],m)]++; } //统计今年本月往日的大月小建数 //今年不是闰年 if(chinesecalendardata[i]<0xfff) for(m=13-fcmonth;m<=11;m++) y[getbit(chinesecalendardata[i],m)]++; else // 是闰年 { k=chinesecalendardata[i]/0x10000; //按照在闰月前后确定统计的开始场所 p=(fcmonth>k)?13-fcmonth:14-fcmonth; if(k+fcmonth==0)p=13+fcmonth; //本月即是闰月 for(m=p;m<=12;m++) y[getbit(chinesecalendardata[i],m)]++; } //7709即是1920年尾月三十 thedate=7709+y[0]*29+y[1]*30+fcday+fctime*2.0/24; } //---------------------------------------------------------------------------- void __fastcall thsdivinecalendar::getymd() { unsigned short y,m,d,t; thedate.decodedate(&y,&m,&d); fyear=y; fmonth=m; fday=d; thedate.decodetime(&t,&y,&m,&d); ftime=t; } //---------------------------------------------------------------------------- 之上即是公历旧历彼此变换的算法和vcl代码,只有领会了那些算法,你就不难写出其余的步调,我就写了javascript和php的代码,本来php、js的代码大略得多,只须要有公历到旧历的变换就不妨了。即使你想要那些代码和完备的vcl源代码,你就说嘛,你不说我如何领会你想要呢?固然你很有忠心地看着我……,嘿嘿,我又中《谎话西游》的毒了:=)。本来,那些代码你不妨在《电脑喜好者》网站大概我的网页(http://bcbtop.126.com)的网页载入。 http://hugsnow.myetang.com/source/hugsnow1.zip