这个程序是根据一个C版的公历转农历的程序改的,当初改成了VB版的,昨天被我翻出来又改成了伪C++版,因为时间久了,又是几经“转译”,程序未必完美,权当娱乐吧
#include <cstring>
#include <cstdio>
#include <iostream>
using namespace std;
int main()
{
//
///初始化数据
//天干表
const char TianGan[10][3] = {"甲", "乙", "丙", "丁", "戊" , "己", "庚", "辛", "壬", "癸"};
//地支表
const char DiZhi[12][3] = {"子", "丑", "寅", "卯", "辰", "巳" , "午", "未", "申", "酉", "戌", "亥"};
const char ShuXiang[12][3] = {"鼠", "牛", "虎", "兔", "龙", "蛇" , "马", "羊", "猴", "鸡", "狗", "猪"};
const char DayName[30][5] = {"初一", "初二", "初三", "初四", "初五", "初六", "初七", "初八" , "初九", "初十",
"十一", "十二", "十三", "十四", "十五", "十六" , "十七", "十八", "十九", "二十",
"廿一", "廿二", "廿三", "廿四" , "廿五", "廿六", "廿七", "廿八", "廿九", "三十"};
const char MonName[12][5] = {"正", "二", "三", "四", "五", "六" , "七", "八", "九", "十", "十一", "腊"};
const char WuXing[5][3] = {"木", "火", "土", "金", "水"};
//地支对应的五行表,规律怪,与其计算,还不如查表快
const char wuxing[12][3] = {"水", "土", "木", "木", "土", "火" , "火", "土", "金", "金", "土", "水"};
/*
const int NongliData[100]的数据构成:
低16位表示(12个或13个月)每个月是大月还是小月,高16位表示闰哪个月
比如2006年表中10进制464219,16进制0x7155b,
二进制
0000 0000 0000 0111 0001 0101 0101 1011
|--------闰7月------|-------98 *765 4321---|
(*闰月,这里闰7月) 比如2007年表中10进制605,16进制0x25D,
二进制
0000 0000 0000 0000 0000 0010 0101 1011
|--------无闰月-----|--------9 8765 4321---|
*/
const int NongliData[100] = {
2635,333387,1701,1748,267701,694,2391,133423,1175,396438,
3402,3749,331177,1453,694,201326,2350,465197,3221,3402,
400202,2901,1386,267611,605,2349,137515,2709,464533,1738,
2901,330421,1242,2651,199255,1323,529706,3733,1706,398762,
2741,1206,267438,2647,1318,204070,3477,461653,1386,2413,
330077,1197,2637,268877,3365,531109,2900,2922,398042,2395,
1179,267415,2635,661067,1701,1748,398772,2742,2391,330031,
1175,1611,200010,3749,527717,1452,2742,332397,2350,3222,
268949,3402,3493,133973,1386,464219,605,2349,334123,2709,
2890,267946,2773,592565,1210,2651,395863,1323,2707,265877};
//const int MonthAdd[12]是当前月之前的经过的整月天数,二月暂以28天计
const int MonthDay[12] = {0,31,59,90,120,151,181,212,243,273,304,334};
//平年和闰年的月表
const int _Month[2][12]={{31,28,31,30,31,30,31,31,30,31,30,31},
{31,29,31,30,31,30,31,31,30,31,30,31}};
//
//
///输入日期
int year, month, day, hour;
cout << "请输入要查询者的相关内容/n" << endl;
while (cout << "请输入 年份(1922 - 2021):" && cin >> year)
if(year >= 1922 && year <= 2021)
break;
//闰年计算,其实这里可以不用这么精确的计算,直接year % 4 == 0即可,因为年份跨度不大
int leapyear = (year % 4 == 0) && ((year % 100 != 0)||(year % 400 == 0)) ? 1 : 0;
while (cout << "请输入 月份(1 - 12):" && cin >> month)
if(month >= 1 && month <= 12)
break;
while (cout << "请输入 日期(1 - 31):" && cin >> day)
if(day >= 1 && day <= _Month[leapyear][month - 1])
break;
while (cout << "请输入 时刻(0 - 23):" && cin >> hour)
if(hour >= 0 && hour <= 23)
break;
cout << "/n" << year << " - " << month << " - " << day << " - " << hour << endl;
//
//
///预转换
hour = (++hour) >= 24 ? 0 : hour / 2;
//时间转换成时辰
//计算日期差 X<-TheDate->1921-2-8
//1921-2-8(辛酉年庚寅月壬寅日)而1921-1-1(辛酉年戊子月甲子)
int sDay = (year - 1921) * 365 + (year - 1921) / 4 + day + MonthDay[month - 1] - 38;//38是代表是从1921-2-8(正月初一)开始计算,而不是1921-1-1,去除38天
//如今年阳历是闰年(2月有29天),而且当前月份大于2月,经历的总天数加1
if((!(year % 4)) && (month > 2)) sDay = sDay + 1;
//
//
///农历数据转换
bool IsEnd = false;
int mYear = 0, h = 0, TDMonth = 0, TheDate = sDay, mMonth, n;
//逐年逐月减天数
while(!IsEnd) {
if(NongliData[mYear] < 4095) {//判断是否有闰月
mMonth = 11;
}
else {
mMonth = 12; //有闰月,故一年有13个月
++h;
}
n = mMonth;
while(n >= 0) {
int Bit = NongliData[mYear];
Bit = (Bit >> n) & 1;
//大小月补差
if (TheDate <= (29 + Bit)) {//判断天数是否少于当月实际总天数
IsEnd = true; break;
}
++TDMonth; //农历月份累加
TheDate -= 29 + Bit; --n;
}
if(IsEnd)
break;
++mYear; //农历年份累加
}
month = mMonth - n;
TDMonth = TDMonth - h;
day = TheDate;
if (mMonth == 12) {//判断闰月及相关数据调整
if (month < NongliData[mYear] / 65536)
++TDMonth;
else if (month == NongliData[mYear] / 65536) //正好是闰月
month = 1 - month;
else if (month > NongliData[mYear] / 65536) //如果为闰月后面的月份,月份值调整
--month;
}
int Tian[4], Di[4];
///各天干计算:年、月、日、时
Tian[0] = (mYear + 7) % 10;
Tian[1] = (TDMonth + 6) % 10;
Tian[2] = (sDay + 7) % 10;
Tian[3] = ((Tian[2] % 5) * 2 + hour) % 10;
///各地支计算:年、月、日、时
Di[0] = (mYear + 9) % 12;
Di[1] = (TDMonth + 2) % 12;
Di[2] = (sDay + 1) % 12;
Di[3] = hour;
const char *theWuXing[8];
///天干地支对应的五行属性
//年
theWuXing[0] = WuXing[Tian[0] / 2];
theWuXing[1] = wuxing[Di[0]];
//月
theWuXing[2] = WuXing[Tian[1] / 2];
theWuXing[3] = wuxing[Di[1]];
//日
theWuXing[4] = WuXing[Tian[2] / 2];
theWuXing[5] = wuxing[Di[2]];
//时
theWuXing[6] = WuXing[Tian[3] / 2];
theWuXing[7] = wuxing[Di[3]];
//五行统计
bool nWuXing[5] = {true, true, true, true, true};
for(int i = 0; i != 8; ++i)
for(int n = 0; n != 5; ++n)
if(0 == strcmp(theWuXing[i], WuXing[n] ))
nWuXing[n] = false;
char NongliStr[7];
sprintf(NongliStr, "%s%s年", TianGan[Tian[0]], DiZhi[Di[0]]);//显示XX年
char NongliDayStr[13];
//显示(闰)X月
if (month < 0) //判断是否为闰月
sprintf(NongliDayStr, "闰%s月", MonName[-1 * month]);
else
sprintf(NongliDayStr, "%s月", MonName[month]);
strcat(NongliDayStr, DayName[day - 1]);
//
//
///结果输出
cout << "\n农历:" << NongliStr << "(" << ShuXiang[(mYear + 9) % 12] << ") " << NongliDayStr << " " << DiZhi[Di[3]]
<< "时\n" << NongliStr << " " << TianGan[Tian[1]] << DiZhi[Di[1]] << "月 " << TianGan[Tian[2]] << DiZhi[Di[2]]
<< "日 " << TianGan[Tian[3]] << DiZhi[Di[3]] << "时" << "\n\n八字为:"
<< TianGan[Tian[0]] << DiZhi[Di[0]] << TianGan[Tian[1]] << DiZhi[Di[1]] << TianGan[Tian[2]] << DiZhi[Di[2]]
<< TianGan[Tian[3]] << DiZhi[Di[3]] << "\n五行为:" << theWuXing[0] << theWuXing[1] << theWuXing[2] << theWuXing[3]
<< theWuXing[4] << theWuXing[5] << theWuXing[6] << theWuXing[7] << endl;
cout << "五行缺:\t";
for(int i = 0; i != 5; ++i)
if(nWuXing[i])
cout << WuXing[i];
cout << endl;
//
//
return 0;
}
中国的农历是相当博大精深的,此处仅以数据表的方式来查询农历闰月及大小月。同时,这个程序是以正月初一,作为新一年的分界。实际上也有以春分作为新一年的分界的。
P.S 代码显示效果不好,下次改用工具编辑好了再上传