function CnMonthOfDate(Date: TDate): String;//指定日期的农历月 function CnDayOfDate(Date: TDate): String;//指定日期的农历日 function CnDateOfDateStr(Date: TDate): String;//指定日期的农历日期
implementation
//日期是该年的第几天,1月1日为第一天 function DaysNumberOfDate(Date: TDate): Integer; var DaysNumber: Integer; I: Integer; yyyy, mm, dd: Word; begin DecodeDate(Date, yyyy, mm, dd); DaysNumber := 0; for I := 1 to mm - 1 do Inc(DaysNumber, MonthDays[IsLeapYear(yyyy), I]); Inc(DaysNumber, dd); Result := DaysNumber; end;
//日期的农历日期,返回农历格式:月份*100 + 日,负数为闰月 //超出范围则返回0 function CnDateOfDate(Date: TDate): Integer; var CnMonth, CnMonthDays: array[0..15] of Integer;
CnBeginDay, LeapMonth: Integer; yyyy, mm, dd: Word; Bytes: array[0..3] of Byte; I: Integer; CnMonthData: Word; DaysCount, CnDaysCount, ResultMonth, ResultDay: Integer; begin DecodeDate(Date, yyyy, mm, dd); if (yyyy < 1901) or (yyyy > 2050) then begin Result := 0; Exit; end; Bytes[0] := CnData[(yyyy - 1901) * 4]; Bytes[1] := CnData[(yyyy - 1901) * 4 + 1]; Bytes[2] := CnData[(yyyy - 1901) * 4 + 2]; Bytes[3] := CnData[(yyyy - 1901) * 4 + 3]; if (Bytes[0] and $80) <> 0 then CnMonth[0] := 12 else CnMonth[0] := 11; CnBeginDay := (Bytes[0] and $7f); CnMonthData := Bytes[1]; CnMonthData := CnMonthData shl 8; CnMonthData := CnMonthData or Bytes[2]; LeapMonth := Bytes[3];
for I := 15 downto 0 do begin CnMonthDays[15 - I] := 29; if ((1 shl I) and CnMonthData) <> 0 then Inc(CnMonthDays[15 - I]); if CnMonth[15 - I] = LeapMonth then CnMonth[15 - I + 1] := - LeapMonth else begin if CnMonth[15 - I] < 0 then //上月为闰月 CnMonth[15 - I + 1] := - CnMonth[15 - I] + 1 else CnMonth[15 - I + 1] := CnMonth[15 - I] + 1; if CnMonth[15 - I + 1] > 12 then CnMonth[15 - I + 1] := 1; end; end;
DaysCount := DaysNumberOfDate(Date) - 1; if DaysCount <= (CnMonthDays[0] - CnBeginDay) then begin if (yyyy > 1901) and (CnDateOfDate(EncodeDate(yyyy - 1, 12, 31)) < 0) then ResultMonth := - CnMonth[0] else ResultMonth := CnMonth[0]; ResultDay := CnBeginDay + DaysCount; end else begin CnDaysCount := CnMonthDays[0] - CnBeginDay; I := 1; while (CnDaysCount < DaysCount) and (CnDaysCount + CnMonthDays[I] < DaysCount) do begin Inc(CnDaysCount, CnMonthDays[I]); Inc(I); end; ResultMonth := CnMonth[I]; ResultDay := DaysCount - CnDaysCount; end; if ResultMonth > 0 then Result := ResultMonth * 100 + ResultDay else Result := ResultMonth * 100 - ResultDay end;
function CnMonthOfDate(Date: TDate): String; const CnMonthStr: array[1..12] of String = ( '一', '二', '三', '四', '五', '六', '七', '八', '九', '十', '冬', '蜡'); var Month: Integer; begin Month := CnDateOfDate(Date) div 100; if Month < 0 then Result := '闰' + CnMonthStr[-Month] else Result := CnMonthStr[Month] + '月'; end;
function CnDayOfDate(Date: TDate): String; const CnDayStr: array[1..30] of String = ( '初一', '初二', '初三', '初四', '初五', '初六', '初七', '初八', '初九', '初十', '十一', '十二', '十三', '十四', '十五', '十六', '十七', '十八', '十九', '二十', '廿一', '廿二', '廿三', '廿四', '廿五', '廿六', '廿七', '廿八', '廿九', '三十'); var Day: Integer; begin Day := Abs(CnDateOfDate(Date)) mod 100; Result := CnDayStr[Day]; end;
function CnDateOfDateStr(Date: TDate): String; begin Result := CnMonthOfDate(Date) + CnDayOfDate(Date); end;
var LMDay : array[1..13] of integer; InterMonth, InterMonthDays, SLRangeDay : integer;
function IsLeapYear(AYear: Integer): Boolean; begin Result := (AYear mod 4 = 0) and ((AYear mod 100 <> 0) or (AYear mod 400 = 0)); end;
function YearName(LYear : integer) : string; var x, y, ya : integer; begin ya := LYear; if ya < 1 then ya := ya + 1; if ya < 12 then ya := ya + 60; x := (ya + 8 - ((ya + 7) div 10) * 10); y := (ya - ((ya-1) div 12) * 12); result := c1[x]+c2[y]; end;
procedure CovertLunarMonth(magicno : integer); var i, size, m : integer; begin m := magicno; for i := 12 downto 1 do begin size := m mod 2; if size = 0 then LMDay[i] := 29 else LMDay[i] := 30; m := m div 2; end; end;
function DaysPerLunarMonth(LYear, LMonth : Integer) : Integer; begin ProcessMagicStr(LYear); if LMonth < 0 then Result := InterMonthDays else Result := LMDay[LMonth]; end;
procedure Solar2Lunar(SYear, SMonth, SDay : integer; var LYear, LMonth, LDay : integer); var i, day : integer; begin day := 0; if isLeapYear(SYear+1911) then SMDay[2] := 29; ProcessMagicStr(SYear); if SMonth = 1 then day := SDay else begin for i := 1 to SMonth-1 do day := day + SMDay[i]; day := day + SDay; end; if day <= SLRangeDay then begin day := day - SLRangeDay; processmagicstr(SYear-1); for i := 12 downto 1 do begin day := day + LMDay[i]; if day > 0 then break; end; LYear := SYear - 1; LMonth := i; LDay := day; end else begin day := day - SLRangeDay; for i := 1 to InterMonth-1 do begin day := day - LMDay[i]; if day <= 0 then break; end; if day <= 0 then begin LYear := SYear; LMonth := i; LDay := day + LMDay[i]; end else begin day := day - LMDay[InterMonth]; if day <= 0 then begin LYear := SYear; LMonth := InterMonth; LDay := day + LMDay[InterMonth]; end else begin LMDay[InterMonth] := InterMonthDays; for i := InterMonth to 12 do begin day := day - LMDay[i]; if day <= 0 then break; end; if i = InterMonth then LMonth := 0 - InterMonth else LMonth := i; LYear := SYear; LDay := day + LMDay[i]; end; end; end; end;
procedure Lunar2Solar(LYear, LMonth, LDay : integer; var SYear, SMonth, SDay : integer); var i, day : integer; begin day := 0; SYear := LYear; if isLeapYear(SYear+1911) then SMDay[2] := 29; processmagicstr(SYear); if LMonth < 0 then day := LMDay[InterMonth]; if LMonth <> 1 then for i := 1 to LMonth-1 do day := day + LMDay[i]; day := day + LDay + SLRangeDay; if (InterMonth <> 13) and (InterMonth < LMonth) then day := day + InterMonthDays; for i := 1 to 12 do begin day := day - SMDay[i]; if day <= 0 then break; end; if day > 0 then begin SYear := SYear + 1; if isLeapYear(SYear+1911) then SMDay[2] := 29; for i := 1 to 12 do begin day := day - SMDay[i]; if day <= 0 then break; end; end; //i := i - 1; day := day + SMDay[i]; //if i = 0 then begin // i := 12; // SYear := SYear - 1; // day := day + 31; //end;// else //day := day + SMDay[i]; SMonth := i; SDay := day; end;