熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Delphi編程 >> 正文

公歷到農歷的轉換法

2013-11-23 17:46:20  來源: Delphi編程 
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
From:http://tw.wingwit.com/Article/program/Delphi/201311/25056.html
    相關文章
      没有相关文章
    推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.