// สำหรับอัลกอริทึมวันหยุดโปรดดูที่ "การเปรียบเทียบระหว่างปฏิทินจันทรคติและปฏิทินตะวันตกปฏิทินตลอดกาล"
หน่วย CNYEAR;
ส่วนต่อประสาน
ใช้ sysutils;
พิมพ์ tcndate = cardinal;
ฟังก์ชั่น decodegregtocndate (dtgre: tdatetime): tcndate;
ฟังก์ชั่น getgregdateFromcn (cnyear, cnmonth, cnday: word; bleap: boolean = false): tdatetime;
ฟังก์ชั่น gregdatetocnstr (dtgre: tdatetime): สตริง;
ฟังก์ชั่น iScnleap (cndate: tcndate): บูลีน;
การดำเนินการ
const cstdateorg: จำนวนเต็ม = 32900;
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 ตัวเลขสี่หลักสูงคือตำแหน่งของเดือนกระโดด 12 หลักสุดท้ายเป็นเดือนที่ใหญ่และใหญ่เดือนใหญ่คือ 30 วันและเดือนเล็ก ๆ คือ 29 วัน
// เดือนกระโดดโดยทั่วไปถือว่าเป็นเดือนเล็ก ๆ แต่มีสามกรณีพิเศษ 2017/06, 2036/06, 2047/05
// สำหรับกรณีพิเศษค่าสูงสุดในการแสดงตำแหน่ง LEAP เดือนของเดือนกระโดดสูงสี่หลักถูกตั้งค่าเป็น 1 การประมวลผลพิเศษใช้ตัวแปร wleapnormal
// // 2017/06 28330-> 61098 2036/06 27947-> 60715 2047/05 23133-> 55901
// หากคุณต้องการใช้แอสเซมบลีนี่คือข้อความ: ปฏิทินจันทรคติจะไม่ล้าหลังปฏิทินเกรกอเรียนเป็นเวลา 2 เดือน
// แปลงปฏิทิน Gregorian เป็นปฏิทินจันทรคติ
// return: 12 หลักปี + เดือน 4 หลัก + วันที่ 5 หลัก
ฟังก์ชั่น decodegregtocndate (dtgre: tdatetime): tcndate;
วาจา
Idayleave: จำนวนเต็ม;
Wyear, Wmonth, Wday: Word;
ฉัน, J: จำนวนเต็ม;
wbigsmalldist, wleap, wcount, wleapshift: Word;
ฉลากตกลง;
เริ่ม
ผลลัพธ์: = 0;
idayleave: = trunc (dtgre) - cstdateorg;
decodedate (incmonth (dtgre, -1), wyear, wmonth, wday);
ถ้า (idayleave <0) หรือ (iDayleave> 22295) จากนั้นออกจาก;
// เพิ่มข้อยกเว้นสร้าง ('ปัจจุบันนับเป็น 1990-01-27 หลังจาก');
// เพิ่มข้อยกเว้นสร้าง ('ปัจจุบันสามารถนับได้ก่อนปี 2051-02-11');
สำหรับ 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 Digit LEAP MONTH LOGO + 12 หลักปี + 4 หลักเดือน + 5 วันที่ (รวม 22 หลัก)
จบ;
ฟังก์ชั่น iScnleap (cndate: tcndate): บูลีน;
เริ่ม
ผลลัพธ์: = (cndate และ $ 200000) <> 0;
จบ;
ฟังก์ชั่น getgregdateFromcn (cnyear, cnmonth, cnday: word; bleap: boolean = false): tdatetime;
วาจา
ฉัน, J: จำนวนเต็ม;
daycount: จำนวนเต็ม;
Wbigsmalldist, Wleap, Wleapshift: Word;
เริ่ม
// 0101 0100101111 ตัวเลขสี่หลักสูงคือตำแหน่งของเดือนกระโดด 12 หลักสุดท้ายเป็นเดือนที่ใหญ่และใหญ่เดือนใหญ่คือ 30 วันและเดือนเล็ก ๆ คือ 29 วัน
daycount: = 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;
จบสิ้น
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 (dtgre: tdatetime): สตริง;
const hznumber: array [0..10] ของ string = ('zero', 'One', 'Two', 'Three', 'Four', 'Five', 'Six', 'Seven', 'Eight', 'Eight', 'เก้าสิบ');
ฟังก์ชั่น Convertymd (หมายเลข: Word; YMD: Word): String;
วาจา
WTMP: Word;
เริ่ม
ผลลัพธ์: = '';
ถ้า ymd = 1 แล้วเริ่มต้น // ปี
ในขณะที่หมายเลข> 0 เริ่มต้น
ผลลัพธ์: = hznumber [หมายเลข mod 10] + ผลลัพธ์;
หมายเลข: = หมายเลข Div 10;
จบ;
ออก;
จบ;
ถ้าหมายเลข <= 10 จากนั้นเริ่มต้น // เพียง 1 หลักเท่านั้นที่สามารถใช้งานได้
ถ้า ymd = 2 แล้ว // เดือน
ผลลัพธ์: = hznumber [หมายเลข]
อื่น // วัน
ผลลัพธ์: = 'First' + hznumber [number];
ออก;
จบ;
wtmp: = number mod 10;
ถ้า wtmp <> 0 แล้วผลลัพธ์: = hznumber [wtmp];
WTMP: = หมายเลข Div 10;
ผลลัพธ์: = 'Ten'+ผลลัพธ์;
ถ้า wtmp> 1 จากนั้นผลลัพธ์: = hznumber [wtmp] + ผลลัพธ์;
จบ;
วาจา
CNYEAR, CNMONTH, CNDAY: Word;
cndate: tcndate;
strleap: สตริง;
เริ่ม
cndate: = decodegregtocndate (dtgre);
ถ้า cndate = 0 แล้วเริ่มต้น
ผลลัพธ์: = 'อินพุตออกจากขอบเขต';
ออก;
จบ;
cnday: = cndate และ $ 1f;
cnmonth: = (cndate Shr 5) และ $ f;
cnyear: = (cndate shr 9) และ $ fff;
// ตำแหน่งที่ 22 ของการทดสอบคือ 1 ซึ่งหมายถึงเดือนกระโดด
ถ้า iscnleap (cndate) จากนั้น streleap: = '(leap)' elstleap: = '';
ผลลัพธ์: = 'Lunar Calendar' + Convertymd (CNYEAR, 1) + 'Year' + Convertymd (Cnmonth, 2) + 'เดือน'
+ strleap + Convertymd (CNDAY, 3);
จบ;
จบ.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////it ///////////////// ///////////////////////////////////////////////////////////////////////////////
ใช้ CNYEAR;
ขั้นตอน tform1.button1click (ผู้ส่ง: tobject);
เริ่ม
edit1.Text: = gregdatetocnstr (dateTimePicker1.date);
จบ;