- [本篇全文] [回复本文] [本篇作者: top ] [本篇人气: 10]
- 发信人: top (英语六级&&PHP), 信区: Programming
- 标 题: 阴阳历算法
- 发信站: 燕赵 BBS (Tue Apr 8 12:14:16 2003), 转信
- [url]http://linux.tcpip.com.cn[/url]
- 阴阳历算法
- 发言者:kent 发言时间:2001-11-08 12:03:11
- 程序为:
- /*
- prototype: int calconv( struct convdate * );
- struct convdate
- {
- int source; ==0 则输入日期为西历, !=0 则输入为农历
- int solaryear; 输出或输入之西历年份
- int solarmonth; 西历月
- int solardate; 西历日
- int lunaryear; 输出或输入之农历年份
- int lunarmonth; 农历月
- 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 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[] = {
- { 23, 3, 2, 17, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0 }, /* 1936 */
- { 23, 3, 2, 17, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0 }, /* 1936 */
- { 41, 0, 4, 23, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1 },
- { 30, 7, 5, 28, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1 },
- { 49, 0, 6, 33, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1 },
- { 38, 0, 0, 38, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1 }, /* 1940 */
- { 26, 6, 2, 44, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0 },
- { 45, 0, 3, 49, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0 },
- { 35, 0, 4, 54, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1 },
- { 24, 4, 5, 59, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1 }, /* 1944 */
- { 43, 0, 0, 5, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1 },
- { 32, 0, 1, 10, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1 },
- { 21, 2, 2, 15, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1 },
- { 40, 0, 3, 20, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1 }, /* 1948 */
- { 28, 7, 5, 26, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1 },
- { 47, 0, 6, 31, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1 },
- { 36, 0, 0, 36, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0 },
- { 26, 5, 1, 41, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1 }, /* 1952 */
- { 44, 0, 3, 47, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1 },
- { 33, 0, 4, 52, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0 },
- { 23, 3, 5, 57, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1, 1 },
- { 42, 0, 6, 2, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1, 1 }, /* 1956 */
- { 30, 8, 1, 8, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0 },
- { 48, 0, 2, 13, 1, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0 },
- { 48, 0, 2, 13, 1, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0 },
- { 38, 0, 3, 18, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1 },
- { 27, 6, 4, 23, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0 }, /* 1960 */
- { 45, 0, 6, 29, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0 },
- { 35, 0, 0, 34, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1 },
- { 24, 4, 1, 39, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0 },
- { 43, 0, 2, 44, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0 }, /* 1964 */
- { 32, 0, 4, 50, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1 },
- { 20, 3, 5, 55, 1, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0 },
- { 39, 0, 6, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0 },
- { 29, 7, 0, 5, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1 }, /* 1968 */
- { 47, 0, 2, 11, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1 },
- { 36, 0, 3, 16, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0 },
- { 26, 5, 4, 21, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1 },
- { 45, 0, 5, 26, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1 }, /* 1972 */
- { 33, 0, 0, 32, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1 },
- { 22, 4, 1, 37, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1 },
- { 41, 0, 2, 42, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1 },
- { 30, 8, 3, 47, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1 }, /* 1976 */
- { 48, 0, 5, 53, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1 },
- { 37, 0, 6, 58, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1 },
- { 27, 6, 0, 3, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0 },
- { 46, 0, 1, 8, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0 }, /* 1980 */
- { 46, 0, 1, 8, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0 }, /* 1980 */
- { 35, 0, 3, 14, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1 },
- { 24, 4, 4, 19, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1 },
- { 43, 0, 5, 24, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1 },
- { 32, 10, 6, 29, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1 }, /* 1984 */
- { 50, 0, 1, 35, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0 },
- { 39, 0, 2, 40, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1 },
- { 28, 6, 3, 45, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0 },
- { 47, 0, 4, 50, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1 }, /* 1988 */
- { 36, 0, 6, 56, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0 },
- { 26, 5, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1 },
- { 45, 0, 1, 6, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0 },
- { 34, 0, 2, 11, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0 }, /* 1992 */
- { 22, 3, 4, 17, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0 },
- { 40, 0, 5, 22, 1, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0 },
- { 30, 8, 6, 27, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1 },
- { 49, 0, 0, 32, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1 }, /* 1996 */
- { 37, 0, 2, 38, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1 },
- { 27, 5, 3, 43, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1 },
- { 46, 0, 4, 48, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1 },
- { 35, 0, 5, 53, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1 }, /* 2000 */
- { 23, 4, 0, 59, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1 },
- { 42, 0, 1, 4, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1 },
- { 42, 0, 1, 4, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1 },
- { 31, 0, 2, 9, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0 },
- { 21, 2, 3, 14, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1 }, /* 2004 */
- { 39, 0, 5, 20, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1 },
- { 28, 7, 6, 25, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1 },
- { 48, 0, 0, 30, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1 },
- { 37, 0, 1, 35, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1 }, /* 2008 */
- { 25, 5, 3, 41, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1 },
- { 44, 0, 4, 46, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1 },
- { 33, 0, 5, 51, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1 },
- { 22, 4, 6, 56, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0 }, /* 2012 */
- { 40, 0, 1, 2, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0 },
- { 30, 9, 2, 7, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1 },
- { 49, 0, 3, 12, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1 },
- { 38, 0, 4, 17, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0 }, /* 2016 */
- { 27, 6, 6, 23, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1, 1 },
- { 46, 0, 0, 28, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0 },
- { 35, 0, 1, 33, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0 },
- { 24, 4, 2, 38, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1 }, /* 2020 */
- { 42, 0, 4, 44, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1 },
- { 31, 0, 5, 49, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0 },
- { 21, 2, 6, 54, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1 },
- { 40, 0, 0, 59, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1 }, /* 2024 */
- { 40, 0, 0, 59, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1 }, /* 2024 */
- { 28, 6, 2, 5, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0 },
- { 47, 0, 3, 10, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 1 },
- { 36, 0, 4, 15, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1 },
- { 25, 5, 5, 20, 1, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0 }, /* 2028 */
- { 43, 0, 0, 26, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1 },
- { 32, 0, 1, 31, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0 },
- { 22, 3, 2, 36, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0 } };
- #define lastyear (firstyear+sizeof(lunarcal)/sizeof(struct
- taglunarcal)-1)
- /* 西历年每月之日数 */
- int solarcal[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
- /* 西历年每月之累积日数, 平年与闰年 */
- int solardays[2][14] = {
- { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365, 396 },
- { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366, 397 } };
- /* 求此西历年是否为闰年, 返回 0 为平年, 1 为闰年 */
- int getleap( int year )
- {
- if ( year % 400 == 0 )
- 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 )
- 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;
- 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 )
- 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;
- 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;
- }
- 摘自:中华技术网
- 作者:黄晓鸣
复制代码 |