| |
程序为: /*
西历农历转换程式 黄晓鸣 1995,7,25
prototype: int calconv( struct convdate * );
struct convdate { int source; ==0 则输入日期为西历, !=0 则输入为农历 int solaryear; 输出或输入之西历年份 int solarmonth; 西历月 int solardate; 西历日 int lunaryear; 输出或输入之农历年份 int lunarmonth; 农历月 int lunardate; 农历日 int weekday; 该日为星期几 ( 0==星期日, 1==星期一, ... ) int kan; 该日天干 ( 0==甲, 1==乙, ..., 9==癸 ) int chih; 该日地支 ( 0==子, 1==丑, ..., 11==亥 ) };
呼叫时须设定 souce 的值, 若为 0 则为西历转农历, 否则为农历转西历. 然後视 输入为西历或农历来设定西历或农历的年月日. 转换後的年月日会填入结构中( 农 历或西历 ), 以及该日为星期几, 天干地支. 若函式的返回值为 0 表示没有错误, 1 为输入之年份错误, 2 为输入之月份错误, 3 为输入之日期错误. 输入之西历年须在 1937 - 2031 间 输入之农历年须在 1936 - 2030 间 若须扩充, 则增加 lunarcal[]
*/
#define firstyear 1936 /* the first year in lunarcal[] */
struct convdate { int source; int solaryear; int solarmonth; int solardate; int lunaryear; int lunarmonth; int lunardate; int weekday; int kan; int chih; };
struct taglunarcal { int basedays; /* 到西历 1 月 1 日到农历正月初一的累积日数 */ int intercalation; /* 闰月月份. 0==此年没有闰月 */ int baseweekday; /* 此年西历 1 月 1 日为星期几再减 1 */ int basekanchih; /* 此年西历 1 月 1 日之干支序号减 1 */ int monthdays[13]; /* 此农历年每月之大小, 0==小月(29日), 1==大月(30日)*/ };
struct taglunarcal lunarcal[] = { , /* 1936 */ , , , , /* 1940 */ , , , , /* 1944 */ , , , , /* 1948 */ , , , , /* 1952 */ , , , , /* 1956 */ , , , , /* 1960 */ , , , , /* 1964 */ , , , , /* 1968 */ , , , , /* 1972 */ , , , , /* 1976 */ , , , , /* 1980 */ , , , , /* 1984 */ , , , , /* 1988 */ , , , , /* 1992 */ , , , , /* 1996 */ , , , , /* 2000 */ , , , , /* 2004 */ , , , , /* 2008 */ , , , , /* 2012 */ , , , , /* 2016 */ , , , , /* 2020 */ , , , , /* 2024 */ , , , , /* 2028 */ , , };
#define lastyear (firstyear+sizeof(lunarcal)/sizeof(struct taglunarcal)-1)
/* 西历年每月之日数 */ int solarcal[12] = ;
/* 西历年每月之累积日数, 平年与闰年 */ int solardays[2][14] = { , };
/* 求此西历年是否为闰年, 返回 0 为平年, 1 为闰年 */ int getleap( int year ) { if ( year % 400 == 0 ) return 1; else if ( year % 100 == 0 ) return 0; else if ( year % 4 == 0 ) return 1; else return 0; }
/* 西历农历转换 */ int calconv( struct convdate *cd ) { int leap, d, sm, y, im, l1, l2, acc, i, lm, kc; if ( cd->source == 0 ) /* solar */ { if ( cd->solaryear <= firstyear || cd->solaryear > lastyear ) return 1; sm = cd->solarmonth - 1; if ( sm < 0 || sm > 11 ) return 2; leap = getleap( cd->solaryear ); if ( sm == 1 ) d = leap + 28; else d = solarcal[sm]; if ( cd->solardate < 1 || cd->solardate > d ) return 3; y = cd->solaryear - firstyear; acc = solardays[leap][sm] + cd->solardate; cd->weekday = ( acc + lunarcal[y].baseweekday ) % 7; kc = acc + lunarcal[y].basekanchih; cd->kan = kc % 10; cd->chih = kc % 12; if ( acc <= lunarcal[y].basedays ) { y--; cd->lunaryear = cd->solaryear - 1; leap = getleap( cd->lunaryear ); sm += 12; acc = solardays[leap][sm] + cd->solardate; } else cd->lunaryear = cd->solaryear; l1 = lunarcal[y].basedays; for ( i=0; i<13; i++ ) { l2 = l1 + lunarcal[y].monthdays[i] + 29; if ( acc <= l2 ) break; l1 = l2; } cd->lunarmonth = i + 1; cd->lunardate = acc - l1; im = lunarcal[y].intercalation; if ( im != 0 && cd->lunarmonth > im ) { cd->lunarmonth--; if ( cd->lunarmonth == im ) cd->lunarmonth = -im; } if ( cd->lunarmonth > 12 ) cd->lunarmonth -= 12; } else /* lunar */ { if ( cd->lunaryear < firstyear || cd->lunaryear >= lastyear ) return 1; y = cd->lunaryear - firstyear; im = lunarcal[y].intercalation; lm = cd->lunarmonth; if ( lm < 0 ) { if ( lm != -im ) return 2; } else if ( lm < 1 || lm > 12 ) return 2; if ( im != 0 ) { if ( lm > im ) lm++; else if ( lm == -im ) lm = im + 1; } lm--; if ( cd->lunardate > lunarcal[y].monthdays[lm] + 29 ) return 3; acc = lunarcal[y].basedays; for ( i=0; i acc += lunarcal[y].monthdays[i] + 29; acc += cd->lunardate; leap = getleap( cd->lunaryear ); for ( i=13; i>=0; i-- ) if ( acc > solardays[leap][i] ) break; cd->solardate = acc - solardays[leap][i]; if ( i <= 11 ) { cd->solaryear = cd->lunaryear; cd->solarmonth = i + 1; } else { cd->solaryear = cd->lunaryear + 1; cd->solarmonth = i - 11; } leap = getleap( cd->solaryear ); y = cd->solaryear - firstyear; acc = solardays[leap][cd->solarmonth-1] + cd->solardate; cd->weekday = ( acc + lunarcal[y].baseweekday ) % 7; kc = acc + lunarcal[y].basekanchih; cd->kan = kc % 10; cd->chih = kc % 12; } return 0; }
|
|