阳历(公历)转农历


网上找了一些阳历转农历的代码,但总是有些对不上。

参照百度万年历和好记星的日历,实现了一下1900-2099年之间的阳历转农历。

#include <iostream>

using namespace std;

struct LunarDate
{
	int year;
	int month;
	int day;
	bool isLeap;
	int yearCyl;//cyclic天干地支
	int monCyl;
	int dayCyl;
};


int lunarInfo[]=
{
	// 1899年:0x0AB50  
	0x04BD8, 0x04AE0, 0x0A570, 0x054D5, 0x0D260, 0x0D950, 0x16554, 0x056A0, 0x09AD0, 0x055D2,   // 1900-1909   
	0x04AE0, 0x0A5B6, 0x0A4D0, 0x0D250, 0x1D255, 0x0B540, 0x0D6A0/*0x1D295,0x0B550,0x056A0*/, 0x0ADA2, 0x095B0, 0x14977,   // 1910-1919  
	0x04970, 0x0A4B0, 0x0B4B5, 0x06A50, 0x06D40, 0x1AB54, 0x02B60, 0x09570, 0x052F2, 0x04970,   // 1920-1929  
	0x06566, 0x0D4A0, 0x0EA50, 0x06E95/*0x16A95*/, 0x05AD0, 0x02B60, 0x186E3, 0x092E0, 0x1C8D7, 0x0C950,   // 1930-1939  
	0x0D4A0, 0x1D8A6, 0x0B550, 0x056A0, 0x1A5B4, 0x025D0, 0x092D0, 0x0D2B2, 0x0A950, 0x0B557,   // 1940-1949  
	0x06CA0, 0x0B550, 0x15355, 0x04DA0, 0x0A5B0, 0x14573, 0x052B0, 0x0A9A8, 0x0E950, 0x06AA0,   // 1950-1959  
	0x0AEA6, 0x0AB50, 0x04B60, 0x0AAE4, 0x0A570, 0x05260, 0x0F263, 0x0D950, 0x05B57, 0x056A0,   // 1960-1969  
	0x096D0, 0x04DD5, 0x04AD0, 0x0A4D0, 0x0D4D4, 0x0D250, 0x0D558, 0x0B540, 0x0B6A0, 0x195A6,   // 1970-1979  
	0x095B0, 0x049B0, 0x0A974, 0x0A4B0, 0x0B27A, 0x06A50, 0x06D40, 0x0AF46, 0x0AB60, 0x09570,   // 1980-1989  
	0x04AF5, 0x04970, 0x064B0, 0x074A3, 0x0EA50, 0x06B58, 0x055C0/*0x05AC0*/, 0x0AB60, 0x096D5, 0x092E0,   // 1990-1999  
	0x0C960, 0x0D954, 0x0D4A0, 0x0DA50, 0x07552, 0x056A0, 0x0ABB7, 0x025D0, 0x092D0, 0x0CAB5,   // 2000-2009  
	0x0A950, 0x0B4A0, 0x0BAA4, 0x0AD50, 0x055D9, 0x04BA0, 0x0A5B0, 0x15176, 0x052B0, 0x0A930,   // 2010-2019
	0x07954, 0x06AA0, 0x0AD50, 0x05B52, 0x04B60, 0x0A6E6, 0x0A4E0, 0x0D260, 0x0EA65, 0x0D530,   // 2020-2029  
	0x05AA0, 0x076A3, 0x096D0, 0x04BD7/*0x04AFB*/, 0x04AD0, 0x0A4D0, 0x1D0B6, 0x0D250, 0x0D520, 0x0DD45,   // 2030-2039  
	0x0B5A0, 0x056D0, 0x055B2, 0x049B0, 0x0A577, 0x0A4B0, 0x0AA50, 0x1B255, 0x06D20, 0x0ADA0,   // 2040-2049  
	// 增加2050-2100年数据  
	0x14B63, 0x09370, 0x049F8, 0x04970, 0x064B0, 0x168A6, 0x0EA50, 0x06B20, 0x1A6C4, 0x0AAE0,   // 2050-2059  
	0x092E0, 0x0D2E3, 0x0C960, 0x0D557, 0x0D4A0, 0x0DA50, 0x05D55, 0x056A0, 0x0A6D0, 0x055D4,   // 2060-2069  
	0x052D0, 0x0A9B8, 0x0A950, 0x0B4A0, 0x0B6A6, 0x0AD50, 0x055A0, 0x0ABA4, 0x0A5B0, 0x052B0,   // 2070-2079  
	0x0B273, 0x06930, 0x07337, 0x06AA0, 0x0AD50, 0x14B55, 0x04B60, 0x0A570, 0x054E4, 0x0D260,   // 2080-2089  
	0x0E968, 0x0D520, 0x0DAA0, 0x16AA6, 0x056D0, 0x04AE0, 0x0A9D4, 0x0A4D0, 0x0D150, 0x0F252,   // 2090-2099  
	0x0D520,                                                                                    // 2100  
};  

//==== 传回农历 y年闰哪个月 1-12 , 没闰传回 0
int GetLunarLeapMonth(int y) 
{ 
	return(lunarInfo[y-1900] & 0xf);
}

//==== 传回农历 y年闰月的天数
int GetLunarLeapDays(int y) 
{
	if(GetLunarLeapMonth(y))  return((lunarInfo[y-1900] & 0x10000)? 30: 29);
	else return(0);
}

//==== 传回农历 y年的总天数
int GetLunarYearDays(int y) 
{
	int i, sum = 348;
	for(i=0x8000; i>0x8; i>>=1) sum += (lunarInfo[y-1900] & i)? 1: 0;
	return sum+GetLunarLeapDays(y);
}

//====================================== 传回农历 y年m月的总天数
int GetLunarMonthDays(int y,int m) 
{ 
	if ( y >= 1900 )   
		return(lunarInfo[y-1900] & (0x10000>>m))? 30: 29 ;
	else if ( (y == 1899) && (m == 12) )   
		return 30;   
	else   
		return 0; 
}

int GetSolarYearDays(int year) 
{ 
	if(year%4==0&&year%100!=0||year%400==0) 
		return 366; 
	else 
		return 365; 
}
int GetSolarMonthDays(int year,int month) 
{ 
	if(month==1||month==3||month==5||month==7||month==8||month==10||month==12) 
		return 31; 
	if(month==4||month==6||month==9||month==11) 
		return 30; 
	if(month==2&&GetSolarYearDays(year)==366) 
		return 29; 
	else 
		return 28; 
} 

int GetDaysFrom19000131(int solarYear, int solarMonth,int solarDay)
{ 
	int     nRecYear;   
	int     nDays;    
	// 1900年不是闰年,2000年是闰年,所以从1901年起每4年必有一个闰年   
	if ( solarYear >= 1901 )   
	{   
		nRecYear = solarYear - 1901;   
		nDays = (nRecYear * 365) + (nRecYear / 4);   
		nDays += 365;   // 1900年是365天   
	}   
	else   
	{ 
		nDays = 0;   
	}   

	for (int i = 1; i < solarMonth; i++)
		nDays += GetSolarMonthDays(solarYear,i);

	nDays += (solarDay - 31);

	return  nDays;
}
//==== 算出农历, 传入日期物件, 传回农历日期物件
//     该物件属性有 .year .month .day .isLeap .yearCyl .dayCyl .monCyl
struct LunarDate GetLunar(int solaryear, int solarmonth,int day) 
{
	struct LunarDate lunar;
	int i, leap=0, temp=0;
	int offset   = GetDaysFrom19000131(solaryear,solarmonth,day);
	lunar.dayCyl = offset + 40;
	lunar.monCyl = 14;  

	for(i=1900; i< 2100 && offset>0; i++) 
	{ 
		temp=GetLunarYearDays(i); 
		if (offset < temp)
			break;
		offset-=temp; 
	}

	lunar.year = i;
	lunar.yearCyl = i-1864;
	leap = GetLunarLeapMonth(i); //闰哪个月
	lunar.isLeap = false;

	for(i=1; i<13; i++) 
	{
		//闰月
		if(leap>0 && i==(leap+1) && !lunar.isLeap)
		{ 
			--i; 
			lunar.isLeap = true; 
			temp = GetLunarLeapDays(lunar.year); 
		}
		else
		{ 
			temp = GetLunarMonthDays(lunar.year, i);
		}
		//解除闰月
		if(lunar.isLeap && i==(leap+1)) 
		{
			lunar.isLeap = false;
		}
		if (offset < temp)
			break;
		offset -= temp;
	}

	lunar.month = i;
	lunar.day = offset + 1;
	return lunar;
}

int main(int argc,char** args)
{
	struct LunarDate lunar = GetLunar(2011,8,23);
	cout<<lunar.year<<"-"<<lunar.month<<"-"<<lunar.day<<endl;
	return 0;
}


你可能感兴趣的:(阳历(公历)转农历)