西西河

主题:请教:谁能给一个公历和农历的对照算法.举个例子: -- 步战将军

共:💬4 新:
分页树展主题 · 全看
  • 家园 请教:谁能给一个公历和农历的对照算法.举个例子:

    2004年8月15日对应农历甲申(猴)年六月三十.

    谢谢!

    • 家园 偶不懂编程,找了一个Javascript的,将军兄自己看一下吧

      一、首先任意处粘贴下面的代码

      <!--

      var bsYear;

      var bsDate;

      var bsWeek;

      var arrLen=8; //数组长度

      var svalue=0; //当年的秒数

      var dayiy=0; //当年第几天

      var miy=0; //月份的下标

      var iyear=0; //年份标记

      var dayim=0; //当月第几天

      var spd=86400; //每天的秒数

      var year1999="30;29;29;30;29;29;30;29;30;30;30;29"; //354

      var year2000="30;30;29;29;30;29;29;30;29;30;30;29"; //354

      var year2001="30;30;29;30;29;30;29;29;30;29;30;29;30"; //384

      var year2002="30;30;29;30;29;30;29;29;30;29;30;29"; //354

      var year2003="30;30;29;30;30;29;30;29;29;30;29;30"; //355

      var year2004="29;30;29;30;30;29;30;29;30;29;30;29;30"; //384

      var year2005="29;30;29;30;29;30;30;29;30;29;30;29"; //354

      var year2006="30;29;30;29;30;30;29;29;30;30;29;29;30";

      var month1999="正月;二月;三月;四月;五月;六月;七月;八月;九月;十月;十一月;十二月"

      var month2001="正月;二月;三月;四月;闰四月;五月;六月;七月;八月;九月;十月;十一月;十二月"

      var month2004="正月;二月;闰二月;三月;四月;五月;六月;七月;八月;九月;十月;十一月;十二月"

      var month2006="正月;二月;三月;四月;五月;六月;七月;闰七月;八月;九月;十月;十一月;十二月"

      var Dn="初一;初二;初三;初四;初五;初六;初七;初八;初九;初十;十一;十二;十三;十四;十五;十六;十七;十八;十九;二十;廿一;廿二;廿三;廿四;廿五;廿六;廿七;廿八;廿九;三十";

      var Ys=new Array(arrLen);

      Ys[0]=919094400;Ys[1]=949680000;Ys[2]=980265600;

      Ys[3]=1013443200;Ys[4]=1044028800;Ys[5]=1074700800;

      Ys[6]=1107878400;Ys[7]=1138464000;

      var Yn=new Array(arrLen); //农历年的名称

      Yn[0]="己卯年";Yn[1]="庚辰年";Yn[2]="辛巳年";

      Yn[3]="壬午年";Yn[4]="癸未年";Yn[5]="甲申年";

      Yn[6]="乙酉年";Yn[7]="丙戌年";

      var D=new Date();

      var yy=D.getYear();

      var mm=D.getMonth()+1;

      var dd=D.getDate();

      var ww=D.getDay();

      if (ww==0) ww="<font color=RED>星期日";

      if (ww==1) ww="星期一";

      if (ww==2) ww="星期二";

      if (ww==3) ww="星期三";

      if (ww==4) ww="星期四";

      if (ww==5) ww="星期五";

      if (ww==6) ww="<font color=RED>星期六";

      ww=ww;

      var ss=parseInt(D.getTime() / 1000);

      if (yy<100) yy="19"+yy;

      for (i=0;i<arrLen;i++)

      if (ss>=Ys[i]){

      iyear=i;

      svalue=ss-Ys[i]; //当年的秒数

      }

      dayiy=parseInt(svalue/spd)+1; //当年的天数

      var dpm=year1999;

      if (iyear==1) dpm=year2000;

      if (iyear==2) dpm=year2001;

      if (iyear==3) dpm=year2002;

      if (iyear==4) dpm=year2003;

      if (iyear==5) dpm=year2004;

      if (iyear==6) dpm=year2005;

      if (iyear==7) dpm=year2006;

      dpm=dpm.split(";");

      var Mn=month1999;

      if (iyear==2) Mn=month2001;

      if (iyear==5) Mn=month2004;

      if (iyear==7) Mn=month2006;

      Mn=Mn.split(";");

      var Dn="初一;初二;初三;初四;初五;初六;初七;初八;初九;初十;十一;十二;十三;十四;十五;十六;十七;十八;十九;二十;廿一;廿二;廿三;廿四;廿五;廿六;廿七;廿八;廿九;三十";

      Dn=Dn.split(";");

      dayim=dayiy;

      var total=new Array(13);

      total[0]=parseInt(dpm[0]);

      for (i=1;i<dpm.length-1;i++) total[i]=parseInt(dpm[i])+total[i-1];

      for (i=dpm.length-1;i>0;i--)

      if (dayim>total[i-1]){

      dayim=dayim-total[i-1];

      miy=i;

      }

      bsWeek=ww;

      bsDate=yy+"年"+mm+"月";

      bsDate2=dd;

      bsYear="农历"+Yn[iyear];

      bsYear2=Mn[miy]+Dn[dayim-1];

      if (ss>=Ys[7]||ss<Ys[0]) bsYear=Yn[7];

      function CAL(){

      document.write("<table border='1' cellspacing='3' width='90' bordercolor='#009B00' bgcolor='#FFFFFF' height='110' cellpadding='2'");

      document.write("<tr><td align='center'><b><font color=#008040>"+bsDate+"</font><br><font face='Arial' size='6' color=#FF8040>"+bsDate2+"</font><br><font color=#008040><span style='FONT-SIZE: 10.5pt'>");

      document.write(bsWeek+"</span><br>"+"<br></b><font color=#9B4E00>");

      document.write(bsYear+"<br>"+bsYear2+"</td></tr></table>");

      }

      //-->

      二、然后在<body></body>之间在你想放置日期的地方粘贴右边的代码

      <script language="javascript">CAL();</script>

      • 家园 【文摘】还有一份delphi的例程

        发信人: HIFI (~ZZZ), 信区: program

        标 题: Re: 公历和农历的关系!

        发信站: 交大兵马俑BBS站 (Sun Jul 11 23:26:28 1999), 转信

        【 在 star (光明来到乐) 的大作中提到: 】

        ∶ 有这种算法吗?

        ∶ 从来没见过

        ∶ 有的话我也要一份

        ∶ 【 在 ZiXiM (浙客西蒙) 的大作中提到: 】

        给你一个delphi的例程:

        (我也是抄的,算法就请自己分析了.)

        unit CNYear;

        interface

        uses sysutils;

        type TCNDate = Cardinal;

        function DecodeGregToCNDate(dtGreg:TDateTime):TCNDate;

        function GetGregDateFromCN(cnYear,cnMonth,cnDay:word;bLeap:Boolean=False):

        TDateTime;

        function GregDateToCNStr(dtGreg:TDateTime):String;

        function isCNLeap(cnDate:TCNDate):boolean;

        implementation

        const cstDateOrg:Integer=32900; //公历1990-01-27的TDateTime表示 对应农历19

        90-01-01

        const cstCNYearOrg=1990;

        const cstCNTable:array[cstCNYearOrg..cstCNYearOrg + 60] of WORD=( //

        unsigned 16-bit

        24402, 3730, 3366, 13614, 2647, 35542, 858, 1749, //1997

        23401, 1865, 1683, 19099, 1323, 2651, 10926, 1386, //2005

        32213, 2980, 2889, 23891, 2709, 1325, 17757, 2741, //2013

        39850, 1490, 3493, 61098, 3402, 3221, 19102, 1366, //2021

        2773, 10970, 1746, 26469, 1829, 1611, 22103, 3243, //2029

        1370, 13678, 2902, 48978, 2898, 2853, 60715, 2635, //2037

        1195, 21179, 1453, 2922, 11690, 3474, 32421, 3365, //2045

        2645, 55901, 1206, 1461, 14038);

        //2050

        //建表方法:

        // 0101 111101010010 高四位是闰月位置,后12位表示大小月,大月30天,小月29

        天,

        //闰月一般算小月,但是有三个特例2017/06,2036/06,2047/05

        //对于特例则高四位的闰月位置表示法中的最高为设置为1 特殊处理用wLeapNormal变

        // //2017/06 28330->61098 2036/06 27947->60715 2047/05 23133->55901

        //如果希望用汇编,这里有一条信息:农历不会滞后公历2个月.

        //将公历转换为农历

        //返回:12位年份+4位月份+5位日期

        function DecodeGregToCNDate(dtGreg:TDateTime):TCNDate;

        var

        iDayLeave:Integer;

        wYear,wMonth,wDay:WORD;

        i,j:integer;

        wBigSmallDist,wLeap,wCount,wLeapShift:WORD;

        label OK;

        begin

        result := 0;

        iDayLeave := Trunc(dtGreg) - cstDateOrg;

        DecodeDate(IncMonth(dtGreg,-1),wYear,wMonth,wDay);

        if (iDayLeave < 0) or (iDayLeave > 22295 )then Exit;

        //Raise Exception.Create('目前只能算1990-01-27以后的');

        //Raise Exception.Create('目前只能算2051-02-11以前的');

        for i:=Low(cstCNTable) to High(cstCNTable) do begin

        wBigSmallDist := cstCNTable[i];

        wLeap := wBigSmallDist shr 12;

        if wLeap > 12 then begin

        wLeap := wLeap and 7;

        wLeapShift := 1;

        end else

        wLeapShift := 0;

        for j:=1 to 12 do begin

        wCount:=(wBigSmallDist and 1) + 29;

        if j=wLeap then wCount := wCount - wLeapShift;

        if iDayLeave < wCount then begin

        Result := (i shl 9) + (j shl 5) + iDayLeave + 1;

        Exit;

        end;

        iDayLeave := iDayLeave - wCount;

        if j=wLeap then begin

        wCount:=29 + wLeapShift;

        if iDayLeave < wCount then begin

        Result := (i shl 9) + (j shl 5) + iDayLeave + 1 + (1 shl

        21);

        Exit;

        end;

        iDayLeave := iDayLeave - wCount;

        end;

        wBigSmallDist := wBigSmallDist shr 1;

        end;

        end;

        //返回值:

        // 1位闰月标志 + 12位年份+4位月份+5位日期 (共22位)

        end;

        function isCNLeap(cnDate:TCNDate):boolean;

        begin

        result := (cnDate and $200000) <> 0;

        end;

        function GetGregDateFromCN(cnYear,cnMonth,cnDay:word;bLeap:Boolean=False):

        TDateTime;

        var

        i,j:integer;

        DayCount:integer;

        wBigSmallDist,wLeap,wLeapShift:WORD;

        begin

        // 0101 010010101111 高四位是闰月位置,后12位表示大小月,大月30天,小月

        29天,

        DayCount := 0;

        if (cnYear < 1990) or (cnYear >2050) then begin

        Result := 0;

        Exit;

        end;

        for i:= cstCNYearOrg to cnYear-1 do begin

        wBigSmallDist := cstCNTable[i];

        if (wBIgSmallDist and $F000) <> 0 then DayCount := DayCount + 29;

        DayCount := DayCount + 12 * 29;

        for j:= 1 to 12 do begin

        DayCount := DayCount + wBigSmallDist and 1;

        wBigSmallDist := wBigSmallDist shr 1;

        end;

        end;

        wBigSmallDist := cstCNTable[cnYear];

        wLeap := wBigSmallDist shr 12;

        if wLeap > 12 then begin

        wLeap := wLeap and 7;

        wLeapShift := 1; //大月在闰月.

        end else

        wLeapShift := 0;

        for j:= 1 to cnMonth-1 do begin

        DayCount:=DayCount + (wBigSmallDist and 1) + 29;

        if j=wLeap then DayCount := DayCount + 29;

        wBigSmallDist := wBigSmallDist shr 1;

        end;

        if bLeap and (cnMonth = wLeap) then //是要闰月的吗?

        DayCount := DayCount + 30 - wLeapShift;

        result := cstDateOrg + DayCount + cnDay - 1;

        end;

        //将日期显示成农历字符串.

        function GregDateToCNStr(dtGreg:TDateTime):String;

        const hzNumber:array[0..10] of string=('零','一','二','三','四','五','六',

        '七','八','九','十');

        function ConvertYMD(Number:Word;YMD:Word):string;

        var

        wTmp:word;

        begin

        result := '';

        if YMD = 1 then begin //年份

        while Number > 0 do begin

        result := hzNumber[Number Mod 10] + result;

        Number := Number DIV 10;

        end;

        Exit;

        end;

        if Number<=10 then begin //可只用1位

        if YMD = 2 then //月份

        result := hzNumber[Number]

        else //天

        result := '初' + hzNumber[Number];

        Exit;

        end;

        wTmp := Number Mod 10; //个位

        if wTmp <> 0 then result := hzNumber[wTmp];

        wTmp := Number Div 10; //十位

        result:='十'+result;

        if wTmp > 1 then result := hzNumber[wTmp] + result;

        end;

        var

        cnYear,cnMonth,cnDay:word;

        cnDate:TCNDate;

        strLeap:string;

        begin

        cnDate:= DecodeGregToCNDate(dtGreg);

        if cnDate = 0 then begin

        result := '输入越界';

        Exit;

        end;

        cnDay := cnDate and $1F;

        cnMonth := (cnDate shr 5) and $F;

        cnYear := (cnDate shr 9) and $FFF;

        //测试第22位,为1表示闰月

        if isCNLeap(cnDate) then strLeap:='(闰)' else strLeap := '';

        result := '农历' + ConvertYMD(cnYear,1) + '年' + ConvertYMD(cnMonth,2) +

        '月'

        + strLeap + ConvertYMD(cnDay,3) ;

        end;

        end.

分页树展主题 · 全看


有趣有益,互惠互利;开阔视野,博采众长。
虚拟的网络,真实的人。天南地北客,相逢皆朋友

Copyright © cchere 西西河