精華區beta mud 關於我們 聯絡資訊
作者 jjchen.bbs@bbs.ntnu.edu.tw (陳金進), 看板 mud 標題 MudOS 陰陽曆轉換程式 時間 師大計中(精靈之城) (Sun Mar 9 08:19:03 1997) 路徑 maple!news.cs.nthu!news.cis.nctu!news.cc.nctu!cc.ntnu!elfBBS!bbs ─────────────────────────────────────── /* 本程式是由 黃曉鳴 於 1995/07/25 發表的程式改編的 原程式請見交大資工 BBS 站的 programming 內的精華區 wade 改寫於 1996 03 08 */ inherit F_CLEAN_UP; // 這是轉換時必須的資料庫, 如果要增加容許轉換的年份, 就必須 // 查萬年曆, 將之填入本資料庫內... // 底下是依次序給與說明 // BaseDays 到西曆 1 月 1 日到農曆正月初一的累積日數 // Intercalation 閏月月份. 0==此年沒有閏月 // BaseWeekday 此年西曆 1 月 1 日為星期幾再減 1 // BaseKanChih 此年西曆 1 月 1 日之干支序號減 1 // 後面是農曆年每月之大小, 0==小月(29日), 1==大月(30日) mixed 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 FIRSTYEAR 1936 // 可以轉換的第一年 #define LASTYEAR FIRSTYEAR+sizeof(LunarCal)-1 // 可以轉換的最後一年 // 西曆年每月之日數 int *SolarCal = ({ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }); /* 西曆年每月之累積日數, 平年與閏年 */ mixed SolarDays = ({ ({ 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 }) }); 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==亥 ) // 求此西曆年是否為閏年, 返回 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() { int leap, d, sm, y, im, l1, l2, acc, i, lm, kc; if (Source == 0) { if ( SolarYear <= FIRSTYEAR || SolarYear > LASTYEAR ) return 1; sm = SolarMonth - 1; if ( sm < 0 || sm > 11 ) return 2; leap = GetLeap( SolarYear ); if ( sm == 1 ) d = leap + 28; else d = SolarCal[sm]; if ( SolarDate < 1 || SolarDate > d ) return 3; y = SolarYear - FIRSTYEAR; acc = SolarDays[leap][sm] + SolarDate; Weekday = ( acc + LunarCal[y][2] ) % 7; kc = acc + LunarCal[y][3]; Kan = kc % 10; Chih = kc % 12; if ( acc <= LunarCal[y][0]) { y--; LunarYear = SolarYear - 1; leap = GetLeap( LunarYear ); sm += 12; acc = SolarDays[leap][sm] + SolarDate; } else LunarYear = SolarYear; l1 = LunarCal[y][0]; for ( i=0; i<13; i++ ) { l2 = l1 + LunarCal[y][i+4] + 29; if ( acc <= l2 ) break; l1 = l2; } LunarMonth = i + 1; LunarDate = acc - l1; im = LunarCal[y][1]; if ( im != 0 && LunarMonth > im ) { LunarMonth--; if ( LunarMonth == im ) LunarMonth = -im; } if ( LunarMonth > 12 ) LunarMonth -= 12; } else /* Lunar */ { if ( LunarYear < FIRSTYEAR || LunarYear >= LASTYEAR ) return 1; y = LunarYear - FIRSTYEAR; im = LunarCal[y][1]; lm = 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 ( LunarDate > LunarCal[y][lm+4] + 29 ) return 3; acc = LunarCal[y][0]; for ( i=0; i<lm; i++ ) acc += LunarCal[y][i+4] + 29; acc += LunarDate; leap = GetLeap( LunarYear ); for ( i=13; i>=0; i-- ) if ( acc > SolarDays[leap][i] ) break; SolarDate = acc - SolarDays[leap][i]; if ( i <= 11 ) { SolarYear = LunarYear; SolarMonth = i + 1; } else { SolarYear = LunarYear + 1; SolarMonth = i - 11; } leap = GetLeap( SolarYear ); y = SolarYear - FIRSTYEAR; acc = SolarDays[leap][SolarMonth-1] + SolarDate; Weekday = ( acc + LunarCal[y][2]) % 7; kc = acc + LunarCal[y][3]; Kan = kc % 10; Chih = kc % 12; } return 0; } int main(object me, string arg) { int yy,mm,dd; int OK=0; if (!arg || arg == "" || sscanf (arg, "%d%d%d", yy, mm, dd) != 3) { write ("語法: lunar 年 月 日\n"); return 1; } if (yy <= 2031 && yy >= 1937 && mm <= 12 && mm >= 1 && dd <= 31 && dd >= 1) { SolarYear = yy; SolarMonth = mm; SolarDate = dd; Source = 0; CalConv(); printf ("Year\t: %d\nMonth\t: %d\nDate:\t: %d\n", LunarYear, LunarMonth, LunarDate); } else printf ("只能查 %d 到 %d 年之間.\n", FIRSTYEAR, LASTYEAR); return 1; }