// 휴일 알고리즘의 경우 "음력 달력과 서부 달력, 영구 달력의 비교"를 참조하십시오.
단위 cnyear;
인터페이스
sysutils를 사용합니다.
TCNDATE = Cardinal 형;
함수 decodeGregrTocndate (dtGreg : tdateTime) : tcndate;
함수는 getGregrgetatefromcn (cnyear, cnmonth, cnday : word; bleap : boolean = false) : tdateTime;
함수 gregdatetocnstr (dtgreg : tdateTime) : 문자열;
기능 iscnleap (cndate : tcndate) : 부울;
구현
Const Cstdateorg : 정수 = 32900; // Gregorian Calendar 1990-01-27의 TdateTime은 해당 음력 1990-01-01을 나타냅니다.
const cstcnyearorg = 1990;
const cstcntable : array [cstcnyearorg..cstcnyearorg + 60] Word = (// 서명되지 않은 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 일입니다.
// 도약의 달은 일반적으로 작은 달로 간주되지만 2017/06, 2036/06, 2047/05 세 가지 특별한 사례가 있습니다.
// 특별한 경우, 4 자리 높은 도약의 달의 도약 월 위치 표현에서 가장 높은 것은 1으로 설정됩니다. 특별 처리는 wleapnormal 변수를 사용합니다.
// // 2017/06 28330-> 61098 2036/06 27947-> 60715 2047/05 23133-> 55901
// 어셈블리를 사용하려면 다음과 같은 메시지가 있습니다. 음력 달력은 2 개월 동안 그레고리 캘린더 뒤에 지연되지 않습니다.
// Gregorian 캘린더를 음력 캘린더로 변환합니다
// 반품 : 12 자리 + 4 자리 월 + 5 자리 날짜
함수 decodeGregrTocndate (dtGreg : tdateTime) : tcndate;
var
Idayleave : 정수;
Wyear, Wmonth, Wday : Word;
I, J : 정수;
WBIGSMALLDIST, WLEAP, WCOUNT, WLEAPSHIFT : Word;
라벨 OK;
시작하다
결과 : = 0;
Idayleave : = trunc (dtgreg) -CstDateorg;
디코딩 드 (Incmonth (dtgreg, -1), wyear, wmonth, wday);
if (idayleave <0) 또는 (idayleave> 22295)을 종료합니다.
// 예외를 올리십시오.
// 예외를 올리십시오.
i : = 낮음 (cstcntable)에서 높음 (cstcntable)이 시작됩니다
wbigsmalldist : = cstcntable [i];
WLEAP : = WBIGSMALLDIST SHR 12;
wleap> 12가 시작되면 시작하십시오
WLEAP : = WLEAP 및 7;
WLEAPSHIFT : = 1;
다른 끝
WLEAPSHIFT : = 0;
J : = 1 ~ 12의 경우 시작됩니다
wcount : = (WBIGSMALLDIST 및 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 자리 도약 달 로고 + 12 자리 연도 + 4 자리 월 + 5 자리 날짜 (총 22 자리)
끝;
기능 iscnleap (cndate : tcndate) : 부울;
시작하다
결과 : = (cndate 및 $ 200000) <> 0;
끝;
함수는 getGregrgetatefromcn (cnyear, cnmonth, cnday : word; bleap : boolean = false) : tdateTime;
var
I, J : 정수;
데이 카운트 : 정수;
WBIGSMALLDIST, WLEAP, WLEAPSHIFT : Word;
시작하다
// 0101 0100101111 높은 4 자리는 도약의 위치, 마지막 12 자리는 큰 달을 나타내고 큰 달은 30 일이며 작은 달은 29 일입니다.
데이 카운트 : = 0;
if (cnyear <1990) 또는 (cnyear> 2050)을 시작하십시오
결과 : = 0;
출구;
끝;
i : = cnyear-1에 대한 cstcnyearorg가 시작됩니다
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; 큰 달은 도약입니다.
다른 끝
WLEAPSHIFT : = 0;
J : = 1에서 cnmonth-1에서 시작됩니다
DayCount : = DayCount + (WBIGSMALLDIST 및 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) : 문자열;
const hznumber : 배열 [0..10]의 String = ( 'Zero', 'One', 'Two', 'Three', 'Four', 'Five', 'Six', 'Seven', '8', '구십');
함수 convertymd (숫자 : Word; ymd : word) : 문자열;
var
WTMP : 단어;
시작하다
결과 : = '';
ymd = 1 인 경우 // 년 시작
숫자> 0이 시작됩니다
결과 : = hznumber [번호 모드 10] + 결과;
숫자 : = 번호 div 10;
끝;
출구;
끝;
숫자 <= 10 인 경우 시작 // 1 자리 만 사용할 수 있습니다.
ymd = 2 인 경우 // 월
결과 : = hznumber [번호]
else // day
결과 : = '첫 번째' + hznumber [숫자];
출구;
끝;
WTMP : = 번호 모드 10;
wtmp <> 0 인 경우 결과 : = hznumber [wtmp];
wtmp : = 번호 div 10;
결과 : = '10'+결과;
wtmp> 1 인 경우 결과 : = hznumber [wtmp] + result;
끝;
var
cnyear, cnmonth, cnday : 단어;
cndate : tcndate;
strleap : 문자열;
시작하다
cndate : = decodegregtocndate (dtgreg);
cndate = 0이면 시작하십시오
결과 : = '경계에서 입력';
출구;
끝;
cnday : = cndate 및 $ 1f;
cnmonth : = (cndate shr 5) 및 $ f;
cnyear : = (cndate sh 9) 및 $ fff;
// 테스트의 22 번째 위치는 1입니다. 이는 도약의 달을 의미합니다.
iScnleap (cndate)이라면 strleap : = '(leap)'else strleap : = '';
결과 : = '음력 달력' + convertymd (cnyear, 1) + 'year' + convertymd (cnmonth, 2) + 'Month'
+ strleap + convertymd (cnday, 3);
끝;
끝.
//////////////////////////////////////////////////////////////////////////////////4 ////////////// ///////////////
cnyear를 사용합니다.
절차 tform1.Button1click (sender : tobject);
시작하다
edit1.text : = gregdatetocnstr (datetimepicker1.date);
끝;