给一个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. 

解决方案 »

  1.   

    unit Calendar;interfaceuses SysUtils,Windows;const
      START_YEAR=1901;
      END_YEAR=2050;// ==> function IsLeapYear(Year: Word): Boolean;//计算iYear,iMonth,iDay对应是星期几 1年1月1日 --- 65535年12月31日
    function WeekDay(iYear,iMonth,iDay:Word):Integer;
    // ==> function DayOfWeek(Date: TDateTime): Integer;//计算指定日期的周数,周0为新年开始后第一个星期天开始的周
    function WeekNum(const TDT:TDateTime):Word;overload;
    function WeekNum(const iYear,iMonth,iDay:Word):Word;overload;//返回iYear年iMonth月的天数 1年1月 --- 65535年12月
    function MonthDays(iYear,iMonth:Word):Word;//返回阴历iLunarYer年阴历iLunarMonth月的天数,如果iLunarMonth为闰月,
    //高字为第二个iLunarMonth月的天数,否则高字为0
    // 1901年1月---2050年12月
    function LunarMonthDays(iLunarYear,iLunarMonth:Word):Longword;//返回阴历iLunarYear年的总天数
    // 1901年1月---2050年12月
    function LunarYearDays(iLunarYear:Word):Word;//返回阴历iLunarYear年的闰月月份,如没有返回0
    // 1901年1月---2050年12月
    function GetLeapMonth(iLunarYear:Word):Word;//把iYear年格式化成天干记年法表示的字符串
    procedure FormatLunarYear(iYear:Word;var pBuffer:string);overload;
    function FormatLunarYear(iYear:Word):string;overload;//把iMonth格式化成中文字符串
    procedure FormatMonth(iMonth:Word;var pBuffer:string;bLunar:Boolean=True);overload;
    function FormatMonth(iMonth:Word;bLunar:Boolean=True):string;overload;//把iDay格式化成中文字符串
    procedure FormatLunarDay(iDay:Word;var pBuffer:string);overload;
    function FormatLunarDay(iDay:Word):string;overload;//计算公历两个日期间相差的天数  1年1月1日 --- 65535年12月31日
    function CalcDateDiff(iEndYear,iEndMonth,iEndDay:Word;iStartYear:Word=START_YEAR;iStartMonth:Word=1;iStartDay:Word=1):Longword;overload;
    function CalcDateDiff(EndDate,StartDate:TDateTime):Longword;overload;//计算公历iYear年iMonth月iDay日对应的阴历日期,返回对应的阴历节气 0-24
    //1901年1月1日---2050年12月31日
    function GetLunarDate(iYear,iMonth,iDay:Word;var iLunarYear,iLunarMonth,iLunarDay:Word):Word;overload;
    procedure GetLunarDate(InDate:TDateTime;var iLunarYear,iLunarMonth,iLunarDay:Word);overload;function GetLunarHolDay(InDate:TDateTime):string;overload;
    function GetLunarHolDay(iYear,iMonth,iDay:Word):string;overload;//private function--------------------------------------//计算从1901年1月1日过iSpanDays天后的阴历日期
    procedure l_CalcLunarDate(var iYear,iMonth,iDay:Word;iSpanDays:Longword);//计算公历iYear年iMonth月iDay日对应的节气 0-24,0表不是节气
    function l_GetLunarHolDay(iYear,iMonth,iDay:Word):Word;implementationvar
    //数组gLunarDay存入阴历1901年到2100年每年中的月天数信息,
    //阴历每月只能是29或30天,一年用12(或13)个二进制位表示,对应位为1表30天,否则为29天
      gLunarMonthDay:array[0..149] of Word=(
        //测试数据只有1901.1.1 --2050.12.31
        $4ae0, $a570, $5268, $d260, $d950, $6aa8, $56a0, $9ad0, $4ae8, $4ae0,   //1910
        $a4d8, $a4d0, $d250, $d548, $b550, $56a0, $96d0, $95b0, $49b8, $49b0,   //1920
        $a4b0, $b258, $6a50, $6d40, $ada8, $2b60, $9570, $4978, $4970, $64b0,   //1930
        $d4a0, $ea50, $6d48, $5ad0, $2b60, $9370, $92e0, $c968, $c950, $d4a0,   //1940
        $da50, $b550, $56a0, $aad8, $25d0, $92d0, $c958, $a950, $b4a8, $6ca0,   //1950
        $b550, $55a8, $4da0, $a5b0, $52b8, $52b0, $a950, $e950, $6aa0, $ad50,   //1960
        $ab50, $4b60, $a570, $a570, $5260, $e930, $d950, $5aa8, $56a0, $96d0,   //1970
        $4ae8, $4ad0, $a4d0, $d268, $d250, $d528, $b540, $b6a0, $96d0, $95b0,   //1980
        $49b0, $a4b8, $a4b0, $b258, $6a50, $6d40, $ada0, $ab60, $9370, $4978,   //1990
        $4970, $64b0, $6a50, $ea50, $6b28, $5ac0, $ab60, $9368, $92e0, $c960,   //2000
        $d4a8, $d4a0, $da50, $5aa8, $56a0, $aad8, $25d0, $92d0, $c958, $a950,   //2010
        $b4a0, $b550, $b550, $55a8, $4ba0, $a5b0, $52b8, $52b0, $a930, $74a8,   //2020
        $6aa0, $ad50, $4da8, $4b60, $9570, $a4e0, $d260, $e930, $d530, $5aa0,   //2030
        $6b50, $96d0, $4ae8, $4ad0, $a4d0, $d258, $d250, $d520, $daa0, $b5a0,   //2040
        $56d0, $4ad8, $49b0, $a4b8, $a4b0, $aa50, $b528, $6d20, $ada0, $55b0);  //2050//数组gLanarMonth存放阴历1901年到2050年闰月的月份,如没有则为0,每字节存两年
      gLunarMonth:array[0..74] of Byte=(
        $00, $50, $04, $00, $20,   //1910
        $60, $05, $00, $20, $70,   //1920
        $05, $00, $40, $02, $06,   //1930
        $00, $50, $03, $07, $00,   //1940
        $60, $04, $00, $20, $70,   //1950
        $05, $00, $30, $80, $06,   //1960
        $00, $40, $03, $07, $00,   //1970
        $50, $04, $08, $00, $60,   //1980
        $04, $0a, $00, $60, $05,   //1990
        $00, $30, $80, $05, $00,   //2000
        $40, $02, $07, $00, $50,   //2010
        $04, $09, $00, $60, $04,   //2020
        $00, $20, $60, $05, $00,   //2030
        $30, $b0, $06, $00, $50,   //2040
        $02, $07, $00, $50, $03);  //2050
      

  2.   

    谢谢各位,但请问gamedragon(gamedragon) , 数组gLunarMonthDay:array[0..149]中的那些数值是怎幺得出来的 ? 谢谢!!!
      

  3.   

    我给个C的。阴阳历算法
    程序为: /*西历农历转换程式prototype: int calconv( struct convdate * );struct convdate
    {
        int source; ==0 则输入日期为西历, !=0 则输入为农历
        int solaryear; 输出或输入之西历年份
        int solarmonth; 西历月
        int solardate; 西历日
        int lunaryear; 输出或输入之农历年份
        int lunarmonth; 农历月
        int lunardate; 农历日
        int weekday; 该日为星期几 ( 0==星期日, 1==星期一, ... )
        int kan; 该日天干 ( 0==甲, 1==乙, ..., 9==癸 )
        int chih; 该日地支 ( 0==子, 1==丑, ..., 11==亥 )
    };呼叫时须设定 souce 的值, 若为 0 则为西历转农历, 否则为农历转西历. 然後视
    输入为西历或农历来设定西历或农历的年月日. 转换後的年月日会填入结构中( 农
    历或西历 ), 以及该日为星期几, 天干地支.
    若函式的返回值为 0 表示没有错误, 1 为输入之年份错误, 2 为输入之月份错误,
    3 为输入之日期错误.
    输入之西历年须在 1937 - 2031 间
    输入之农历年须在 1936 - 2030 间
    若须扩充, 则增加 lunarcal[]*/#define firstyear 1936 /* the first year in lunarcal[] */struct convdate
    {
        int source;
        int solaryear;
        int solarmonth;
        int solardate;
        int lunaryear;
        int lunarmonth;
        int lunardate;
        int weekday;
        int kan;
        int chih;
    };struct taglunarcal
    {
        int basedays; /* 到西历 1 月 1 日到农历正月初一的累积日数 */
        int intercalation; /* 闰月月份. 0==此年没有闰月 */
        int baseweekday; /* 此年西历 1 月 1 日为星期几再减 1 */
        int basekanchih; /* 此年西历 1 月 1 日之干支序号减 1 */
        int monthdays[13]; /* 此农历年每月之大小, 0==小月(29日), 1==大月(30日)*/
    };struct taglunarcal lunarcal[] = {
    { 23, 3, 2, 17, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0 }, /* 1936 */
    { 41, 0, 4, 23, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1 },
    { 30, 7, 5, 28, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1 },
    { 49, 0, 6, 33, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1 },
    { 38, 0, 0, 38, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1 }, /* 1940 */
    { 26, 6, 2, 44, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0 },
    { 45, 0, 3, 49, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0 },
    { 35, 0, 4, 54, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1 },
    { 24, 4, 5, 59, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1 }, /* 1944 */
    { 43, 0, 0, 5, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1 },
    { 32, 0, 1, 10, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1 },
    { 21, 2, 2, 15, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1 },
    { 40, 0, 3, 20, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1 }, /* 1948 */
    { 28, 7, 5, 26, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1 },
    { 47, 0, 6, 31, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1 },
    { 36, 0, 0, 36, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0 },
    { 26, 5, 1, 41, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1 }, /* 1952 */
    { 44, 0, 3, 47, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1 },
    { 33, 0, 4, 52, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0 },
    { 23, 3, 5, 57, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1, 1 },
    { 42, 0, 6, 2, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1, 1 }, /* 1956 */
    { 30, 8, 1, 8, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0 },
    { 48, 0, 2, 13, 1, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0 },
    { 38, 0, 3, 18, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1 },
    { 27, 6, 4, 23, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0 }, /* 1960 */
    { 45, 0, 6, 29, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0 },
    { 35, 0, 0, 34, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1 },
    { 24, 4, 1, 39, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0 },
    { 43, 0, 2, 44, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0 }, /* 1964 */
    { 32, 0, 4, 50, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1 },
    { 20, 3, 5, 55, 1, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0 },
    { 39, 0, 6, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0 },
    { 29, 7, 0, 5, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1 }, /* 1968 */
    { 47, 0, 2, 11, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1 },
    { 36, 0, 3, 16, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0 },
    { 26, 5, 4, 21, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1 },
    { 45, 0, 5, 26, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1 }, /* 1972 */
    { 33, 0, 0, 32, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1 },
    { 22, 4, 1, 37, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1 },
    { 41, 0, 2, 42, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1 },
    { 30, 8, 3, 47, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1 }, /* 1976 */
    { 48, 0, 5, 53, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1 },
    { 37, 0, 6, 58, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1 },
    { 27, 6, 0, 3, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0 },
    { 46, 0, 1, 8, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0 }, /* 1980 */
    { 35, 0, 3, 14, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1 },
    { 24, 4, 4, 19, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1 },
    { 43, 0, 5, 24, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1 },
    { 32, 10, 6, 29, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1 }, /* 1984 */
    { 50, 0, 1, 35, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0 },
    { 39, 0, 2, 40, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1 },
    { 28, 6, 3, 45, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0 },
    { 47, 0, 4, 50, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1 }, /* 1988 */
    { 36, 0, 6, 56, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0 },
    { 26, 5, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1 },
    { 45, 0, 1, 6, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0 },
    { 34, 0, 2, 11, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0 }, /* 1992 */
    { 22, 3, 4, 17, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0 },
    { 40, 0, 5, 22, 1, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0 },
    { 30, 8, 6, 27, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1 },
    { 49, 0, 0, 32, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1 }, /* 1996 */
    { 37, 0, 2, 38, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1 },
    { 27, 5, 3, 43, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1 },
    { 46, 0, 4, 48, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1 },
    { 35, 0, 5, 53, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1 }, /* 2000 */
    { 23, 4, 0, 59, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1 },
    { 42, 0, 1, 4, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1 },
    { 31, 0, 2, 9, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0 },
    { 21, 2, 3, 14, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1 }, /* 2004 */
    { 39, 0, 5, 20, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1 },
    { 28, 7, 6, 25, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1 },
    { 48, 0, 0, 30, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1 },
    { 37, 0, 1, 35, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1 }, /* 2008 */
    { 25, 5, 3, 41, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1 },
    { 44, 0, 4, 46, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1 },
    { 33, 0, 5, 51, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1 },
    { 22, 4, 6, 56, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0 }, /* 2012 */
    { 40, 0, 1, 2, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0 },
    { 30, 9, 2, 7, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1 },
    { 49, 0, 3, 12, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1 },
    { 38, 0, 4, 17, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0 }, /* 2016 */
    { 27, 6, 6, 23, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1, 1 },
    { 46, 0, 0, 28, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0 },
    { 35, 0, 1, 33, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0 },
    { 24, 4, 2, 38, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1 }, /* 2020 */
    { 42, 0, 4, 44, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1 },
    { 31, 0, 5, 49, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0 },
    { 21, 2, 6, 54, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1 },
    { 40, 0, 0, 59, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1 }, /* 2024 */
    { 28, 6, 2, 5, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0 },
    { 47, 0, 3, 10, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 1 },
    { 36, 0, 4, 15, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1 },
    { 25, 5, 5, 20, 1, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0 }, /* 2028 */
    { 43, 0, 0, 26, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1 },
    { 32, 0, 1, 31, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0 },
    { 22, 3, 2, 36, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0 } };
      

  4.   


    #define lastyear (firstyear+sizeof(lunarcal)/sizeof(struct taglunarcal)-1)/* 西历年每月之日数 */
    int solarcal[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };/* 西历年每月之累积日数, 平年与闰年 */
    int solardays[2][14] = {
    { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365, 396 },
    { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366, 397 } };/* 求此西历年是否为闰年, 返回 0 为平年, 1 为闰年 */
    int getleap( int year )
    {
        if ( year % 400 == 0 )
            return 1;
        else if ( year % 100 == 0 )
            return 0;
        else if ( year % 4 == 0 )
            return 1;
        else
            return 0;
    }/* 西历农历转换 */
    int calconv( struct convdate *cd )
    {
        int leap, d, sm, y, im, l1, l2, acc, i, lm, kc;
        if ( cd->source == 0 ) /* solar */
        {
            if ( cd->solaryear <= firstyear || cd->solaryear > lastyear )
                return 1;
            sm = cd->solarmonth - 1;
            if ( sm < 0 || sm > 11 )
                return 2;
            leap = getleap( cd->solaryear );
            if ( sm == 1 )
                d = leap + 28;
            else
                d = solarcal[sm];
            if ( cd->solardate < 1 || cd->solardate > d )
                return 3;
            y = cd->solaryear - firstyear;
            acc = solardays[leap][sm] + cd->solardate;
            cd->weekday = ( acc + lunarcal[y].baseweekday ) % 7;
            kc = acc + lunarcal[y].basekanchih;
            cd->kan = kc % 10;
            cd->chih = kc % 12;
            if ( acc <= lunarcal[y].basedays )
            {
                y--;
                cd->lunaryear = cd->solaryear - 1;
                leap = getleap( cd->lunaryear );
                sm += 12;
                acc = solardays[leap][sm] + cd->solardate;
            }
        else
            cd->lunaryear = cd->solaryear;
        l1 = lunarcal[y].basedays;
        for ( i=0; i<13; i++ )
        {
            l2 = l1 + lunarcal[y].monthdays[i] + 29;
            if ( acc <= l2 )
                break;
            l1 = l2;
        }
        cd->lunarmonth = i + 1;
        cd->lunardate = acc - l1;
        im = lunarcal[y].intercalation;
        if ( im != 0 && cd->lunarmonth > im )
        {
            cd->lunarmonth--;
            if ( cd->lunarmonth == im )
                cd->lunarmonth = -im;
        }
        if ( cd->lunarmonth > 12 )
            cd->lunarmonth -= 12;
        }
        else /* lunar */
        {
            if ( cd->lunaryear < firstyear || cd->lunaryear >= lastyear )
                return 1;
            y = cd->lunaryear - firstyear;
            im = lunarcal[y].intercalation;
            lm = cd->lunarmonth;
            if ( lm < 0 )
            {
                if ( lm != -im )
                    return 2;
            }
            else if ( lm < 1 || lm > 12 )
                return 2;
            if ( im != 0 )
            {
                if ( lm > im )
                    lm++;
                else if ( lm == -im )
                    lm = im + 1;
            }
            lm--;
            if ( cd->lunardate > lunarcal[y].monthdays[lm] + 29 )
                return 3;
            acc = lunarcal[y].basedays;
            for ( i=0; i acc += lunarcal[y].monthdays[i] + 29;
                acc += cd->lunardate;
                leap = getleap( cd->lunaryear );
            for ( i=13; i>=0; i-- )
                if ( acc > solardays[leap][i] )
                    break;
                cd->solardate = acc - solardays[leap][i];
                if ( i <= 11 )
                {
                    cd->solaryear = cd->lunaryear;
                    cd->solarmonth = i + 1;
                }
                else
                {
                    cd->solaryear = cd->lunaryear + 1;
                    cd->solarmonth = i - 11;
                }
                leap = getleap( cd->solaryear );
                y = cd->solaryear - firstyear;
                acc = solardays[leap][cd->solarmonth-1] + cd->solardate;
                cd->weekday = ( acc + lunarcal[y].baseweekday ) % 7;
                kc = acc + lunarcal[y].basekanchih;
                cd->kan = kc % 10;
                cd->chih = kc % 12;
            }
    return 0;

     
      

  5.   

    请教codewarrior(会思考的草)  lunarcal[]中的值您是怎么推算出来的,这是我最关心的问题,谢谢您的指教!