电脑故障

位置:IT落伍者 >> 电脑故障 >> 浏览文章

公历到农历的转换法


发布日期:2022/2/18
 
unit CNYear;

interface

uses sysutils;

type TCNDate = Cardinal;

function DecodeGregToCNDate(dtGreg:TDateTime):TCNDate;

function GetGregDateFromCN(cnYearcnMonthcnDay:word;bLeap:Boolean=False):

TDateTime;

function GregDateToCNStr(dtGreg:TDateTime):String;

function isCNLeap(cnDate:TCNDate):boolean;

implementation

const cstDateOrg:Integer=; //公历的TDateTime表示 对应农历

const cstCNYearOrg=;

const cstCNTable:array[cstCNYearOrgcstCNYearOrg + ] of WORD=( //

unsigned bit

//

//

//

//

//

//

//

);

//

//建表方法

// 高四位是闰月位置位表示大小月大月小月

//闰月一般算小月但是有三个特例///

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

// /// > / > / >

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

//将公历转换为农历

//返回:位年份+位月份+位日期

function DecodeGregToCNDate(dtGreg:TDateTime):TCNDate;

var

iDayLeave:Integer;

wYearwMonthwDay:WORD;

ij:integer;

wBigSmallDistwLeapwCountwLeapShift:WORD;

label OK;

begin

result := ;

iDayLeave := Trunc(dtGreg) cstDateOrg;

DecodeDate(IncMonth(dtGreg)wYearwMonthwDay);

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

//Raise ExceptionCreate(目前只能算以后的);

//Raise ExceptionCreate(目前只能算以前的);

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

wBigSmallDist := cstCNTable[i];

wLeap := wBigSmallDist shr ;

if wLeap > then begin

wLeap := wLeap and ;

wLeapShift := ;

end else

wLeapShift := ;

for j:= to do begin

wCount:=(wBigSmallDist and ) + ;

if j=wLeap then wCount := wCount wLeapShift;

if iDayLeave < wCount then begin

Result := (i shl ) + (j shl ) + iDayLeave + ;

Exit;

end;

iDayLeave := iDayLeave wCount;

if j=wLeap then begin

wCount:= + wLeapShift;

if iDayLeave < wCount then begin

Result := (i shl ) + (j shl ) + iDayLeave + + ( shl

);

Exit;

end;

iDayLeave := iDayLeave wCount;

end;

wBigSmallDist := wBigSmallDist shr ;

end;

end;

//返回值:

// 位闰月标志 + 位年份+位月份+位日期 (共位)

end;

function isCNLeap(cnDate:TCNDate):boolean;

begin

result := (cnDate and $) <> ;

end;

function GetGregDateFromCN(cnYearcnMonthcnDay:word;bLeap:Boolean=False):

TDateTime;

var

ij:integer;

DayCount:integer;

wBigSmallDistwLeapwLeapShift:WORD;

begin

// 高四位是闰月位置位表示大小月大月小月

DayCount := ;

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

Result := ;

Exit;

end;

for i:= cstCNYearOrg to cnYear do begin

wBigSmallDist := cstCNTable[i];

if (wBIgSmallDist and $F) <> then DayCount := DayCount + ;

DayCount := DayCount + * ;

for j:= to do begin

DayCount := DayCount + wBigSmallDist and ;

wBigSmallDist := wBigSmallDist shr ;

end;

end;

wBigSmallDist := cstCNTable[cnYear];

wLeap := wBigSmallDist shr ;

if wLeap > then begin

wLeap := wLeap and ;

wLeapShift := ; //大月在闰月

end else

wLeapShift := ;

for j:= to cnMonth do begin

DayCount:=DayCount + (wBigSmallDist and ) + ;

if j=wLeap then DayCount := DayCount + ;

wBigSmallDist := wBigSmallDist shr ;

end;

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

DayCount := DayCount + wLeapShift;

result := cstDateOrg + DayCount + cnDay ;

end;

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

function GregDateToCNStr(dtGreg:TDateTime):String;

const hzNumber:array[] of string=(

);

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

var

wTmp:word;

begin

result := ;

if YMD = then begin //年份

while Number > do begin

result := hzNumber[Number Mod ] + result;

Number := Number DIV ;

end;

Exit;

end;

if Number<= then begin //可只用

if YMD = then //月份

result := hzNumber[Number]

else //天

result := + hzNumber[Number];

Exit;

end;

wTmp := Number Mod ; //个位

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

wTmp := Number Div ; //十位

result:=+result;

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

end;

var

cnYearcnMonthcnDay:word;

cnDate:TCNDate;

strLeap:string;

begin

cnDate:= DecodeGregToCNDate(dtGreg);

if cnDate = then begin

result := 输入越界;

Exit;

end;

cnDay := cnDate and $F;

cnMonth := (cnDate shr ) and $F;

cnYear := (cnDate shr ) and $FFF;

//测试第表示闰月

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

result := 农历 + ConvertYMD(cnYear) + + ConvertYMD(cnMonth) +

+ strLeap + ConvertYMD(cnDay) ;

end;

end

上一篇:系统发布&系统扩展

下一篇:经典案例 财务管理系统(10)[1]