﻿	function ChnCalendar()
	{
	}

	ChnCalendar.prototype._lunarInfo=new Array(
	0x04bd8,0x04ae0,0x0a570,0x054d5,0x0d260,0x0d950,0x16554,0x056a0,0x09ad0,0x055d2,
	0x04ae0,0x0a5b6,0x0a4d0,0x0d250,0x1d255,0x0b540,0x0d6a0,0x0ada2,0x095b0,0x14977,
	0x04970,0x0a4b0,0x0b4b5,0x06a50,0x06d40,0x1ab54,0x02b60,0x09570,0x052f2,0x04970,
	0x06566,0x0d4a0,0x0ea50,0x06e95,0x05ad0,0x02b60,0x186e3,0x092e0,0x1c8d7,0x0c950,
	0x0d4a0,0x1d8a6,0x0b550,0x056a0,0x1a5b4,0x025d0,0x092d0,0x0d2b2,0x0a950,0x0b557,
	0x06ca0,0x0b550,0x15355,0x04da0,0x0a5d0,0x14573,0x052d0,0x0a9a8,0x0e950,0x06aa0,
	0x0aea6,0x0ab50,0x04b60,0x0aae4,0x0a570,0x05260,0x0f263,0x0d950,0x05b57,0x056a0,
	0x096d0,0x04dd5,0x04ad0,0x0a4d0,0x0d4d4,0x0d250,0x0d558,0x0b540,0x0b5a0,0x195a6,
	0x095b0,0x049b0,0x0a974,0x0a4b0,0x0b27a,0x06a50,0x06d40,0x0af46,0x0ab60,0x09570,
	0x04af5,0x04970,0x064b0,0x074a3,0x0ea50,0x06b58,0x055c0,0x0ab60,0x096d5,0x092e0,
	0x0c960,0x0d954,0x0d4a0,0x0da50,0x07552,0x056a0,0x0abb7,0x025d0,0x092d0,0x0cab5,
	0x0a950,0x0b4a0,0x0baa4,0x0ad50,0x055d9,0x04ba0,0x0a5b0,0x15176,0x052b0,0x0a930,
	0x07954,0x06aa0,0x0ad50,0x05b52,0x04b60,0x0a6e6,0x0a4e0,0x0d260,0x0ea65,0x0d530,
	0x05aa0,0x076a3,0x096d0,0x04bd7,0x04ad0,0x0a4d0,0x1d0b6,0x0d250,0x0d520,0x0dd45,
	0x0b5a0,0x056d0,0x055b2,0x049b0,0x0a577,0x0a4b0,0x0aa50,0x1b255,0x06d20,0x0ada0);

	ChnCalendar.prototype._solarMonth=new Array(31,28,31,30,31,30,31,31,30,31,30,31);
	ChnCalendar.prototype._Gan=new Array("甲","乙","丙","丁","戊","己","庚","辛","壬","癸");
	ChnCalendar.prototype._Zhi=new Array("子","丑","寅","卯","辰","巳","午","未","申","酉","戌","亥");
	ChnCalendar.prototype._Animals=new Array("鼠","牛","虎","兔","龙","蛇","马","羊","猴","鸡","狗","猪");
	ChnCalendar.prototype._solarTerm = new Array("小寒","大寒","立春","雨水","惊蛰","春分","清明","谷雨","立夏","小满","芒种","夏至","小暑"," 大暑","立秋","处暑","白露","秋分","寒露","霜降","立冬","小雪","大雪","冬至");
	ChnCalendar.prototype._sTermInfo = new Array(0,21208,42467,63836,85337,107014,128867,150921,173149,195551,218072,240693,263343,285989,308563,331033,353350,375494,397447,419210,440795,462224,483532,504758);
	ChnCalendar.prototype._nStr1 = new Array('日','一','二','三','四','五','六','七','八','九','十');
	ChnCalendar.prototype._nStr2 = new Array('初','十','廿','卅','　');
	ChnCalendar.prototype._monthName = new Array("JAN","FEB","MAR","APR","MAY","JUN","JUL","AUG","SEP","OCT","NOV","DEC");

	ChnCalendar.prototype._sFtv = new Array(
	"0101* 元旦"
	);

	ChnCalendar.prototype._lFtv = new Array(
	"0101* 春节",
	"0115 元宵",
	"0505 端午",
	"0707 七夕",
	"0715 中元",
	"0815 中秋",
	"0909 重阳",
	"1208 腊八",
	"1224 小年",
	"0100* 除夕");

	ChnCalendar.prototype._wFtv = new Array();

	ChnCalendar.prototype._lYearDays = function(y) 
	{
		var i, sum = 348;
		for(i=0x8000; i>0x8; i>>=1) 
		{
			var diffYear = y-1900;
			sum += (ChnCalendar.prototype._lunarInfo[diffYear] & i)? 1: 0;
		}
		return(sum + ChnCalendar.prototype._leapDays(y));
	};

	ChnCalendar.prototype._leapMonth = function(y) 
	{
		var diffYear = y-1900;
		
		return(ChnCalendar.prototype._lunarInfo[diffYear] & 0xf);
	};
	
	ChnCalendar.prototype._leapDays = function(y) 
	{
		if(ChnCalendar.prototype._leapMonth(y)) 
		{
			var diffYear = y-1900;
			return((ChnCalendar.prototype._lunarInfo[diffYear] & 0x10000)? 30: 29);
		}
		else 
		{
			return(0);
		}
	};


	ChnCalendar.prototype._monthDays = function(y,m) 
	{
		var diffYear = y-1900;
		return( (ChnCalendar.prototype._lunarInfo[diffYear] & (0x10000>>m))? 30: 29 );
	};
	

	ChnCalendar.prototype.getLunarDay = function(objDate) 
	{
		var objChnDate = new Object();
		var i, leap=0, temp=0;
		var baseDate = new Date(1900,0,31);
		var offset = Math.ceil((objDate - baseDate)/86400000);
		
		objChnDate.dayCyl = offset + 40;
		objChnDate.monCyl = 14;
		
		for(i=1900; i<2050 && offset>0; i++) 
		{
			temp = ChnCalendar.prototype._lYearDays(i);
			offset -= temp;
			objChnDate.monCyl += 12;
		}
		
		if(offset<0)
		{
			offset += temp;
			i--;
			objChnDate.monCyl -= 12;
		}
		
		objChnDate.year = i;
		objChnDate.yearCyl = i-1864;
		
		leap = ChnCalendar.prototype._leapMonth(i); //闰哪个月
		objChnDate.isLeap = false;
		
		for(i=1; i<13 && offset>0; i++) {
			
			//闰月
			if(leap>0 && i==(leap+1) && objChnDate.isLeap===false)
			{ 
				--i; objChnDate.isLeap = true; temp = ChnCalendar.prototype._leapDays(objChnDate.year); 
			}
			else
			{ 
				temp = ChnCalendar.prototype._monthDays(objChnDate.year, i); 
			}
			
			//解除闰月
			if(objChnDate.isLeap===true && i==(leap+1))
			{
				objChnDate.isLeap = false;
			}
			
			offset -= temp;
			if(objChnDate.isLeap === false) 
			{
				objChnDate.monCyl ++;
			}
		}
		
		if(offset===0 && leap>0 && i===leap + 1)
		{
			if(objChnDate.isLeap)
			{ 
				objChnDate.isLeap = false; 
			}
			else
			{ 
				objChnDate.isLeap = true; 
				--i; 
				--objChnDate.monCyl;
			}
		}
		
		if(offset<0)
		{
			offset += temp; 
			--i; 
			--objChnDate.monCyl;
		}
		
		objChnDate.month = i;
		objChnDate.day = offset + 1;
		return objChnDate;
	};

	
	ChnCalendar.prototype._solarDays = function(y,m) 
	{
		if(m==1)
		{
			return(((y%4 === 0) && (y%100 !== 0) || (y%400 === 0))? 29: 28);
		}
		else
		{
			return(ChnCalendar.prototype._solarMonth[m]);
		}
		
	};
	
	ChnCalendar.prototype._cyclical = function(num)
	{
		return(ChnCalendar.prototype._Gan[num%10]+ChnCalendar.prototype._Zhi[num%12]);
	};

	//===== 某年的第n个节气为几日(从0小寒起算)
	ChnCalendar.prototype._sTerm= function(y,n) 
	{
		var offDate = new Date( ( 31556925974.7*(y-1900) + ChnCalendar.prototype._sTermInfo[n]*60000 ) + Date.UTC(1900,0,6,2,5) );
		return(offDate.getUTCDate());
	};
	
	ChnCalendar.prototype._cDay = function(d)
	{
		var s;

		switch (d) {
		case 10:
		s = '初十'; break;
		case 20:
		s = '二十'; break;
		break;
		case 30:
		s = '三十'; break;
		break;
		default :
		s = ChnCalendar.prototype._nStr2[Math.floor(d/10)];
		s = s + ChnCalendar.prototype._nStr1[d%10];
		}
		return(s);
	}

	ChnCalendar.prototype.getCalendar = function(y,m) 
	{
		var sDObj, lDObj, lY, lM, lD=1, lL, lX=0, tmp1, tmp2;
		var lDPOS = new Array(3);
		var n = 0;
		var firstLM = 0;
		var cal = new Calendar();
		
		sDObj = new Date(y,m,1); //当月一日日期
		
		cal.length = ChnCalendar.prototype._solarDays(y,m); //国历当月天数
		cal.firstWeek = sDObj.getDay() ;//国历当月1日星期几
		
		for(var i=0;i<cal.length;i++) 
		{
			if(lD>lX) 
			{
				sDObj = new Date(y,m,i+1); //当月一日日期
				lDObj = ChnCalendar.prototype.getLunarDay(sDObj); //农历
				lY = lDObj.year ;//农历年
				lM = lDObj.month ;//农历月
				lD = lDObj.day ;//农历日
				lL = lDObj.isLeap; //农历是否闰月
				lX = lL? ChnCalendar.prototype._leapDays(lY): ChnCalendar.prototype._monthDays(lY,lM); //农历当月最後一天
				
				if(n==0) firstLM = lM;
				lDPOS[n++] = i-lD+1;
			}
		
			//sYear,sMonth,sDay,week,
			//lYear,lMonth,lDay,isLeap,
			//cYear,cMonth,cDay
			cal.elements[i] = new calElement(y, m+1, i+1, ChnCalendar.prototype._nStr1[(i+cal.firstWeek)%7],
			lY, lM, lD++, lL,
			ChnCalendar.prototype._cyclical(lDObj.yearCyl) ,ChnCalendar.prototype._cyclical(lDObj.monCyl), ChnCalendar.prototype._cyclical(lDObj.dayCyl++) );
	
	
			if((i+cal.firstWeek)%7==0) 
			{
				cal.elements[i].color = 'red'; //周日颜色
			}
			if((i+cal.firstWeek)%7==6)
			{
				cal.elements[i].color = 'red' ;//周六颜色
			}
		}
	
		//节气
		tmp1=ChnCalendar.prototype._sTerm(y,m*2 )-1;
		tmp2=ChnCalendar.prototype._sTerm(y,m*2+1)-1;
		cal.elements[tmp1].solarTerms = ChnCalendar.prototype._solarTerm[m*2];
		cal.elements[tmp2].solarTerms = ChnCalendar.prototype._solarTerm[m*2+1];
		if(m==3)
		{
			cal.elements[tmp1].color = 'red'; //清明颜色	
		}
	
		//国历节日
		for(i in ChnCalendar.prototype._sFtv)
		{
			var matchRtn = ChnCalendar.prototype._sFtv[i].match(/^(\d{2})(\d{2})(\*{0,1})(\s+)(.+)/);
			if(matchRtn !== null)  
			{
				
				if(Number(matchRtn[1])==(m+1)) 
				{
					cal.elements[Number(matchRtn[2])-1].solarFestival += matchRtn[5] + ' ';
					if(matchRtn[3]=='*') 
					{
						cal.elements[Number(matchRtn[2])-1].color = 'red';
					}
				}
			}
			
		}
	
		//月周节日
		for(i in ChnCalendar.prototype._wFtv)
		{
			var matchRtn = ChnCalendar.prototype._wFtv[i].match(/^(\d{2})(\d{1})(\d{1})(\*{0,1})(\s+)(.+)/);
			if(matchRtn !== null)
			{
				if(Number(matchRtn[1])==(m+1)) 
				{
					tmp1=Number(matchRtn[2]);
					tmp2=Number(matchRtn[3]);
					cal.elements[((cal.firstWeek>tmp2)?7:0) + 7*(tmp1-1) + tmp2 - cal.firstWeek].solarFestival += matchRtn[6] + ' ';
				}
			}
		}

		//农历节日
		for(i in ChnCalendar.prototype._lFtv)
		{
			var matchRtn = ChnCalendar.prototype._lFtv[i].match(/^(\d{2})(\d{2})(\*{0,1})(\s+)(.+)/);
			if(matchRtn !== null)
			{
				tmp1=Number(matchRtn[1])-firstLM;
				if(tmp1==-11) tmp1=1;
				if(tmp1 >=0 && tmp1<n) 
				{
					tmp2 = lDPOS[tmp1] + Number(matchRtn[2]) -1;
					if( tmp2 >= 0 && tmp2<cal.length) 
					{
						cal.elements[tmp2].lunarFestival += matchRtn[5] + ' ';
						if(matchRtn[3]=='*') {
							cal.elements[tmp2].color = 'red';
						}
					}
				}
			}
		}

		//今日
		var today = new Date();
		var tYear = today.getFullYear();
		var tMonth = today.getMonth();
		var tDay = today.getDate();
	
		if(y==tYear && m==tMonth) 
		{
			cal.elements[tDay-1].isToday = true;
		}
	
		return cal;
	
	
		function Calendar()
		{
			this.elements = new Array();
		}
		
		function calElement(sYear,sMonth,sDay,week,lYear,lMonth,lDay,isLeap,cYear,cMonth,cDay) 
		{
			this.isToday = false;
			//国历
			this.sYear = sYear;
			this.sMonth = sMonth;
			this.sDay = sDay;
			this.week = week;
			//农历
			this.lYear = lYear;
			this.lMonth = lMonth;
			this.lDay = lDay;
			this.isLeap = isLeap;
			//干支
			this.cYear = cYear;
			this.cMonth = cMonth;
			this.cDay = cDay;
			
			this.color = '';
			
			this.lunarFestival = ''; //农历节日
			this.solarFestival = ''; //国历节日
			this.solarTerms = ''; //节气
		}
		
		
	}
