大雀软件园

首页 软件下载 安卓市场 苹果市场 电脑游戏 安卓游戏 文章资讯 驱动下载
技术开发 网页设计 图形图象 数据库 网络媒体 网络安全 站长CLUB 操作系统 媒体动画 安卓相关
当前位置: 首页 -> 技术开发 -> 程序开发 -> 公历农历相互转换的算法及其VCL实现

公历农历相互转换的算法及其VCL实现

时间: 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

热门阅览

最新排行

Copyright © 2019-2021 大雀软件园(www.daque.cn) All Rights Reserved.