Algorithm 版 (精华区)

发信人: sino (茶水博士), 信区: Theory
标  题: [转载]查表法公历/农历转换(100年)
发信站: 哈工大紫丁香 (Sun Aug 27 13:28:43 2000), 转信

发信人: zhch (zhch from nju), 信区: algorithm
发信站: NJU Lily BBS (Tue Mar 23 12:21:13 1999), 站内信件



发信人: smhwang.bbs@csie.nctu (全自动之狼), 信区: programming 
标 题: --- 西历与农历转换函式 --- 
发信站: 交大资工凤凰城资讯站 (Wed Jul 26 01:51:17 1995) 
转信站: cis_nctu!news.cis.nctu!news.csie.nctu!phoenix 

本函式欢迎各站各版转载, 无须经本人同意. 若对历法有兴趣, 欢迎讨论. 

/* 

西历农历转换程式 黄晓鸣 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[] = { 
{ 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 }, 
{ 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 */ 
{ 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 }, 
{ 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 */ 
{ 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 ) 
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; 

--
※ 修改:.fib 於 Aug 27 13:26:24 修改本文.[FROM: bbs.hit.edu.cn]
--
※ 转寄:.南京大学小百合 bbs.nju.edu.cn.[FROM: bbs.hit.edu.cn]

--
☆ 来源:.哈工大紫丁香 bbs.hit.edu.cn.[FROM: fib.bbs@bbs.nju.edu.]
[百宝箱] [返回首页] [上级目录] [根目录] [返回顶部] [刷新] [返回]
Powered by KBS BBS 2.0 (http://dev.kcn.cn)
页面执行时间:206.826毫秒