//ホリデーアルゴリズムについては、「月のカレンダーと西洋カレンダーの比較、永続的なカレンダー」を参照してください。
ユニットCNYEAR;
インタフェース
sysutilsを使用します。
タイプtcndate = cardinal;
関数decodegregtocndate(dtgreg:tdatetime):tcndate;
関数getGregdateFromcn(Cnyear、cnmonth、cnday:word; bleap:boolean = false):tdatetime;
関数gregdateTocnstr(dtgreg:tdatetime):string;
関数ISCNLEAP(cndate:tcndate):boolean;
実装
const cstdateorg:integer = 32900;
const cstcnyearorg = 1990;
const cstcntable:array [cstcnyearorg..cstcnyearorg + 60] of word =(// unsigned 16ビット
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);
//テーブル作成方法:
// 0101 111101010010高4桁は跳躍月の位置であり、最後の12桁は大小の月を表し、大規模な月は30日、小さな月は29日です。
//跳躍月は一般に小さな月と見なされますが、3つの特別なケース2017/06、2036/06、2047/05があります
//特別なケースの場合、4桁の高Leap MonthのLeap Monthの位置表現は1に設定されています。
// // 2017/06 28330-> 61098 2036/06 27947-> 60715 2047/05 23133-> 55901
//アセンブリを使用したい場合は、ここにメッセージがあります。月のカレンダーは2か月間グレゴリオカレンダーの後ろに遅れをとっていません。
//グレゴリオカレンダーを月のカレンダーに変換します
//返品:12桁の年 + 4桁の月 + 5桁の日付
関数decodegregtocndate(dtgreg:tdatetime):tcndate;
var
idayleave:整数;
ワイアー、wmonth、wday:word;
I、J:整数;
wbigsmalldist、wleap、wcount、wleapshift:word;
ラベルOK;
始める
結果:= 0;
idayleave:= trunc(dtgreg)-Cstdateorg;
decodedate(incmnth(dtgreg、-1)、wyear、wmonth、wday);
if(idayleave <0)または(idayleave> 22295)から終了します。
//例外を上げます。create( '現在、1990-01-27の後にのみカウントされています');
//例外を上げます。create( '現在、2051-02-11の前とのみカウントできます');
i:= low(cstcntable)〜high(cstcntable)が始まります
wbigsmalldist:= cstcntable [i];
wleap:= wbigsmalldist shr 12;
WLEAP> 12の場合、開始します
wleap:= wleapおよび7;
wleapshift:= 1;
ENSEを終了します
wleapshift:= 0;
j:= 1から12の場合は開始します
wcount:=(wbigsmalldist and 1) + 29;
j = wleapの場合、wcount:= wcount -wleapshift;
idayleave <wcountの場合、開始します
結果:=(i shl 9) +(j shl 5) + idayleave + 1;
出口;
終わり;
idayleave:= idayleave -wcount;
j = wleapの場合、開始します
wcount:= 29 + wleapshift;
idayleave <wcountの場合、開始します
結果:=(i shl 9) +(j shl 5) + idayleave + 1 +(1 shl 21);
出口;
終わり;
idayleave:= idayleave -wcount;
終わり;
wbigsmalldist:= wbigsmalldist shr 1;
終わり;
終わり;
//返品値:
// 1桁leap月ロゴ + 12桁 + 4桁月 + 5桁の日付(合計22桁)
終わり;
関数ISCNLEAP(cndate:tcndate):boolean;
始める
結果:=(cndateおよび$ 200000)<> 0;
終わり;
関数getGregdateFromcn(Cnyear、cnmonth、cnday:word; bleap:boolean = false):tdatetime;
var
I、J:整数;
デイカウント:整数;
wbigsmalldist、wleap、wleapshift:word;
始める
// 0101 0100101111高い4桁は跳躍月の位置であり、最後の12桁は大小の月を表し、大規模な月は30日、小さな月は29日です。
デイカウント:= 0;
(cnyear <1990)または(cnyear> 2050)の場合、開始します
結果:= 0;
出口;
終わり;
i:= CSTCNYEARORGからCNYEAR-1から始まります
wbigsmalldist:= cstcntable [i];
if(wbigsmalldistと$ f000)<> 0 daycount:= daycount + 29;
daycount:= daycount + 12 * 29;
j:= 1から12の場合は開始します
daycount:= daycount + wbigsmalldistおよび1;
wbigsmalldist:= wbigsmalldist shr 1;
終わり;
終わり;
wbigsmalldist:= cstcntable [cnyear];
wleap:= wbigsmalldist shr 12;
WLEAP> 12の場合、開始します
wleap:= wleapおよび7;
wleapshift:= 1;
ENSEを終了します
wleapshift:= 0;
j:= 1からcnmonth-1の場合は開始します
daycount:= daycount +(wbigsmalldist and 1) + 29;
j = wleapの場合、daycount:= daycount + 29;
wbigsmalldist:= wbigsmalldist shr 1;
終わり;
Bleapおよび(cnmonth = wleap)の場合、//それは跳躍月ですか?
daycount:= daycount + 30 -wleapshift;
結果:= cstdateorg + daycount + cnday -1;
終わり;
//日付を月の文字列に表示します。
関数gregdateTocnstr(dtgreg:tdatetime):string;
const hznumber:string =( 'zero'、 'one'、 'two'、 'three'、 'four'、 'vive'、 'six'、 'seven'、 'eight'の配列[0..10]の配列[0..10] 'ninety');
function convertymd(number:word; ymd:word):string;
var
wtmp:word;
始める
結果:= '';
YMD = 1の場合、//年を開始します
数字> 0が始まります
結果:= hzNumber [number mod 10] + result;
番号:= number div 10;
終わり;
出口;
終わり;
番号<= 10の場合、// 1桁のみを使用できます
ymd = 2 then //月の場合
結果:= hznumber [number]
else // day
結果:= 'first' + hznumber [number];
出口;
終わり;
wtmp:= number mod 10;
wtmp <> 0の場合、結果:= hznumber [wtmp];
wtmp:= number div 10;
結果:= 'Ten'+result;
wtmp> 1の場合、結果:= hznumber [wtmp] + result;
終わり;
var
Cnyear、cnmonth、cnday:word;
cndate:tcndate;
strleap:string;
始める
cndate:= decodegregtocndate(dtgreg);
cndate = 0の場合、開始します
結果:= '境界からの入力';
出口;
終わり;
cnday:= cndateおよび$ 1f;
cnmonth:=(cndate shr 5)および$ f;
Cnyear:=(cndate shr 9)および$ fff;
//テストの22番目の位置は1です。これは、跳躍月を意味します
iscnleap(cndate)の場合、strleap:= '(leap)' else strleap:= '';
結果:= '月カレンダー' + convertymd(cnyear、1) + 'year' + convertymd(cnmonth、2) + 'month'
+ strleap + convertymd(cnday、3);
終わり;
終わり。
///////////////////////////////////////////////// ////////////////////////
CNYEARを使用します。
手順tform1.button1click(sender:tobject);
始める
edit1.text:= gregdatetocnstr(dateTimePicker1.date);
終わり;