#include"TDateTime.h"

/* Not Leap Year
2678400
5097600
7776000
10368000
13046400
15638400
18316800
20995200
23587200
26265600
28857600
31536000


	//month 1			2678400
	2				5097600
	3				7776000
	
	4				10368000
	5				13046400
	6				15638400
	
	7				18316800
	8				20995200
	9				23587200
	
	10				26265600
	11				28857600
	12				31536000
	
	Leap Year
	//month 1		2678400
				5184000
				7862400
				10454400
				13132800
				15724800
				18403200
				21081600
				23673600
				26352000
				28944000
				31622400
				
				2678400
5184000
7862400
10454400
13132800
15724800
18403200
21081600
23673600
26352000
28944000
31622400

126230400

*/

#define dMONTH_1			2678400
#define dMONTH_2			5097600
#define dMONTH_3			7776000
#define dMONTH_4			10368000
#define dMONTH_5			13046400
#define dMONTH_6			15638400
#define dMONTH_7			18316800
#define dMONTH_8			20995200
#define dMONTH_9			23587200
#define dMONTH_10			26265600
#define dMONTH_11			28857600
#define dMONTH_12			31536000

#define dLEAPMONTH_1		2678400
#define dLEAPMONTH_2		5184000
#define dLEAPMONTH_3		7862400
#define dLEAPMONTH_4		10454400
#define dLEAPMONTH_5		13132800
#define dLEAPMONTH_6		15724800
#define dLEAPMONTH_7		18403200
#define dLEAPMONTH_8		21081600
#define dLEAPMONTH_9		23673600
#define dLEAPMONTH_10		26352000
#define dLEAPMONTH_11		28944000
#define dLEAPMONTH_12		31622400

void TDateTime::s__DecodeLeapYearMonth(unsigned int aSec, TDate *pDate)
{
	unsigned int sec = aSec;
	
	if(sec < dLEAPMONTH_3){
		if(sec < dLEAPMONTH_1){
			pDate->Split.Month=1;
			sec = sec - 0;
			pDate->Split.Day = static_cast<unsigned char>(sec / 86400) +1;
		}else
		if(sec < dLEAPMONTH_2){
			pDate->Split.Month=2; 
			sec = sec - dLEAPMONTH_1;
			pDate->Split.Day = static_cast<unsigned char>(sec / 86400) +1;
		}else{
			pDate->Split.Month=3;
			sec = sec - dLEAPMONTH_2;
			pDate->Split.Day = static_cast<unsigned char>(sec / 86400) +1;
		}
	}else
	if(sec < dLEAPMONTH_6){
		if(sec < dLEAPMONTH_4){
			pDate->Split.Month=4;
			sec = sec - dLEAPMONTH_3;
			pDate->Split.Day = static_cast<unsigned char>(sec / 86400) +1;
		}else
		if(sec < dLEAPMONTH_5){
			pDate->Split.Month=5; 
			sec = sec - dLEAPMONTH_4;
			pDate->Split.Day = static_cast<unsigned char>(sec / 86400) +1;
		}else{
			pDate->Split.Month=6;
			sec = sec - dLEAPMONTH_5;
			pDate->Split.Day = static_cast<unsigned char>(sec / 86400) +1;
		}
	}else
	if(sec < dLEAPMONTH_9){
		if(sec < dLEAPMONTH_7){
			pDate->Split.Month=7;
			sec = sec - dLEAPMONTH_6;
			pDate->Split.Day = static_cast<unsigned char>(sec / 86400) +1;
		}else
		if(sec < dLEAPMONTH_8){
			pDate->Split.Month=8; 
			sec = sec - dLEAPMONTH_7;
			pDate->Split.Day = static_cast<unsigned char>(sec / 86400) +1;
		}else{
			pDate->Split.Month=9;
			sec = sec - dLEAPMONTH_8;
			pDate->Split.Day = static_cast<unsigned char>(sec / 86400) +1;
		}
	}else{
		if(sec < dLEAPMONTH_10){
			pDate->Split.Month=10;
			sec = sec - dLEAPMONTH_9;
			pDate->Split.Day = static_cast<unsigned char>(sec / 86400) +1;
		}else
		if(sec < dLEAPMONTH_11){
			pDate->Split.Month=11; 
			sec = sec - dLEAPMONTH_10;
			pDate->Split.Day = static_cast<unsigned char>(sec / 86400) +1;
		}else{
			pDate->Split.Month=12;
			sec = sec - dLEAPMONTH_11;
			pDate->Split.Day = static_cast<unsigned char>(sec / 86400) +1;
		}	
	}	
}

void TDateTime::s__DecodeYearMonth(unsigned int aSec, TDate *pDate)
{
	unsigned int sec = aSec;
	
	if(sec < dMONTH_3){
		if(sec < dMONTH_1){
			pDate->Split.Month=1;
			sec = sec - 0;
			pDate->Split.Day = static_cast<unsigned char>(sec / 86400) +1;
		}else
		if(sec < dMONTH_2){
			pDate->Split.Month=2; 
			sec = sec - dMONTH_1;
			pDate->Split.Day = static_cast<unsigned char>(sec / 86400) +1;
		}else{
			pDate->Split.Month=3;
			sec = sec - dMONTH_2;
			pDate->Split.Day = static_cast<unsigned char>(sec / 86400) +1;
		}
	}else
	if(sec < dMONTH_6){
		if(sec < dMONTH_4){
			pDate->Split.Month=4;
			sec = sec - dMONTH_3;
			pDate->Split.Day = static_cast<unsigned char>(sec / 86400) +1;
		}else
		if(sec < dMONTH_5){
			pDate->Split.Month=5; 
			sec = sec - dMONTH_4;
			pDate->Split.Day = static_cast<unsigned char>(sec / 86400) +1;
		}else{
			pDate->Split.Month=6;
			sec = sec - dMONTH_5;
			pDate->Split.Day = static_cast<unsigned char>(sec / 86400) +1;
		}
	}else
	if(sec < dMONTH_9){
		if(sec < dMONTH_7){
			pDate->Split.Month=7;
			sec = sec - dMONTH_6;
			pDate->Split.Day = static_cast<unsigned char>(sec / 86400) +1;
		}else
		if(sec < dMONTH_8){
			pDate->Split.Month=8; 
			sec = sec - dMONTH_7;
			pDate->Split.Day = static_cast<unsigned char>(sec / 86400) +1;
		}else{
			pDate->Split.Month=9;
			sec = sec - dMONTH_8;
			pDate->Split.Day = static_cast<unsigned char>(sec / 86400) +1;
		}
	}else{
		if(sec < dMONTH_10){
			pDate->Split.Month=10;
			sec = sec - dMONTH_9;
			pDate->Split.Day = static_cast<unsigned char>(sec / 86400) +1;
		}else
		if(sec < dMONTH_11){
			pDate->Split.Month=11; 
			sec = sec - dMONTH_10;
			pDate->Split.Day = static_cast<unsigned char>(sec / 86400) +1;
		}else{
			pDate->Split.Month=12;
			sec = sec - dMONTH_11;
			pDate->Split.Day = static_cast<unsigned char>(sec / 86400) +1;
		}	
	}	
}

void TDateTime::s__EncodeLeapYearMonth(TDate aDate, unsigned int *pSec)
{
	unsigned int aDay;
	if(aDate.Split.Month < 4){
		if(aDate.Split.Month == 2){
			*pSec = *pSec + dLEAPMONTH_1;
		}else
		if(aDate.Split.Month == 3){
			*pSec = *pSec + dLEAPMONTH_2;
		}
	}else
	if(aDate.Split.Month < 7){
		if(aDate.Split.Month == 4){
			*pSec = *pSec + dLEAPMONTH_3;
		}else
		if(aDate.Split.Month == 5){
			*pSec = *pSec + dLEAPMONTH_4;
		}else{
			*pSec = *pSec + dLEAPMONTH_5;
		}
	}else
	if(aDate.Split.Month < 10){
		if(aDate.Split.Month == 7){
			*pSec = *pSec + dLEAPMONTH_6;
		}else
		if(aDate.Split.Month == 8){
			*pSec = *pSec + dLEAPMONTH_7;
		}else{
			*pSec = *pSec + dLEAPMONTH_8;
		}
	}else{
		if(aDate.Split.Month == 10){
			*pSec = *pSec + dLEAPMONTH_9;
		}else
		if(aDate.Split.Month == 11 ){
			*pSec = *pSec + dLEAPMONTH_10;
		}else{
			*pSec = *pSec + dLEAPMONTH_11;
		}	
	}	
	
	if(aDate.Split.Day > 0)aDay = aDate.Split.Day -1;
	else aDay = 0;
	*pSec = *pSec + ( (  static_cast<unsigned int>(aDay)  ) * 86400  );
}
 
void TDateTime::s__EncodeYearMonth(TDate aDate, unsigned int *pSec)
{
	unsigned int aDay;
	if(aDate.Split.Month < 4){
		if(aDate.Split.Month == 2){
			*pSec = *pSec + dMONTH_1;
		}else
		if(aDate.Split.Month == 3){
			*pSec = *pSec + dMONTH_2;
		}
	}else
	if(aDate.Split.Month < 7){
		if(aDate.Split.Month == 4){
			*pSec = *pSec + dMONTH_3;
		}else
		if(aDate.Split.Month == 5){
			*pSec = *pSec + dMONTH_4;
		}else{
			*pSec = *pSec + dMONTH_5;
		}
	}else
	if(aDate.Split.Month < 10){
		if(aDate.Split.Month == 7){
			*pSec = *pSec + dMONTH_6;
		}else
		if(aDate.Split.Month == 8){
			*pSec = *pSec + dMONTH_7;
		}else{
			*pSec = *pSec + dMONTH_8;
		}
	}else{
		if(aDate.Split.Month == 10){
			*pSec = *pSec + dMONTH_9;
		}else
		if(aDate.Split.Month == 11 ){
			*pSec = *pSec + dMONTH_10;
		}else{
			*pSec = *pSec + dMONTH_11;
		}	
	}	
		
	if(aDate.Split.Day > 0)aDay = aDate.Split.Day -1;
	else aDay = 0;
	*pSec = *pSec + ( (  static_cast<unsigned int>(aDay)  ) * 86400  );	
}

void TDateTime::s__DecodeTime(unsigned int sec, TTime *pTime)
{
	unsigned int seconed = sec % 86400;
	pTime->Split.Hour = static_cast<unsigned char>(seconed / 3600);
	seconed = seconed % 3600;
	pTime->Split.Minute = static_cast<unsigned char>(seconed / 60);
	pTime->Split.Second = seconed % 60;
	
	pTime->Split.Rev = 0;
}

void TDateTime::s__EncodeTime(TTime aTime, unsigned int *pSec)
{
	unsigned int sec;
	sec = ( static_cast<unsigned int>(aTime.Split.Hour ) )* 3600;
	sec = sec + (  (static_cast<unsigned int>(aTime.Split.Minute )) * 60);
	sec = sec + aTime.Split.Second;
	
	*pSec = *pSec + sec;
}

void TDateTime::sDecodeDateTime(unsigned int aSec, TDate *pDate, TTime *pTime)
{
	unsigned int Year,sec;

	sec = aSec / 126230400;
	Year = sec * 4 + dDATETIME_BASESTART_YEAR;
	sec = aSec % 126230400;
	
	if(sec < 31622400){
		//LeapYear 
		Year += 0;
		sec = sec - 0;
		s__DecodeLeapYearMonth(sec, pDate);
		s__DecodeTime(sec,pTime);
	}else
	if(sec < 63158400){
		//Not LeapYear 
		Year += 1;
		sec = sec - 31622400;
		s__DecodeYearMonth(sec, pDate);
		s__DecodeTime(sec,pTime);
	}else
	if(sec < 94694400){
		//Not LeapYear 
		Year += 2;
		sec = sec - 63158400;
		s__DecodeYearMonth(sec, pDate);
		s__DecodeTime(sec,pTime);
	}else{
		//Not LeapYear 
		Year += 3;
		sec = sec - 94694400;
		s__DecodeYearMonth(sec, pDate);
		s__DecodeTime(sec,pTime);
	}
	
	pDate->Split.Year = static_cast<unsigned short>(Year);	
}
		

void TDateTime::sEncodeDateTime(TDate aDate, TTime aTime, unsigned int *pSec)
{
	//4 Years (365*4+1)*24*60*60 = 1461 * 86400 = 	126144000 seconed
	//2000,   leap year 366 * 24*60*60 = 366 * 86400 = 	 31622400 seconed		31622400
	//2001,        year 365 * 24*60*60 = 365 * 86400 = 	 31536000 seconed		63158400
	//2002,        year 365 * 24*60*60 = 365 * 86400 = 	 31536000 seconed		94694400
	//2003,        year 365 * 24*60*60 = 365 * 86400 = 	 31536000 seconed	     126144000
	
	unsigned int sec, nmod, idiv;
	
	idiv = (aDate.Split.Year - dDATETIME_BASESTART_YEAR) / 4;
	nmod = (aDate.Split.Year - dDATETIME_BASESTART_YEAR) % 4;
	
	if(nmod == 0){
		//LeapYear 
		sec = 0;
		s__EncodeLeapYearMonth(aDate, &sec);
		s__EncodeTime(aTime, &sec);
	}else
	if(nmod == 1){
		//Not LeapYear 
		sec = 31622400;
		s__EncodeYearMonth(aDate, &sec);
		s__EncodeTime(aTime, &sec);
	}else
	if(nmod == 2){
		//Not LeapYear 
		sec = 63158400;
		s__EncodeYearMonth(aDate, &sec);
		s__EncodeTime(aTime, &sec);
	}else{
		//Not LeapYear 
		sec = 94694400;
		s__EncodeYearMonth(aDate, &sec);
		s__EncodeTime(aTime, &sec);
	}
	
	sec = sec + (idiv * 126230400); 
	*pSec = sec;
}

TDate TDateTime::GetDate(void)
{
	return Date;
}

TTime TDateTime::GetTime(void)
{
	return Time;
}	
		
unsigned int TDateTime::GetDateTime(void)
{
	return DateTimeInSecond;
}
			
void TDateTime::SetDateTimeSplit(TDate aDate, TTime aTime)
{
	Date.FullValue = aDate.FullValue;
	Time.FullValue = aTime.FullValue;
	Time.Split.Rev = 0;
	sEncodeDateTime(Date, Time, &DateTimeInSecond);
}		
		
void TDateTime::SetDateTimeViaSecond(unsigned int aSec)
{
	DateTimeInSecond = aSec;
	sDecodeDateTime(DateTimeInSecond, &Date, &Time);
}


int TDateTime::GetWeek(void)
{
	int day = 0;
	
	int curyear;  
	int Mnt;
	int cyear = 0;              
	int cday = 0;               
	int curmonthday = 0;
	
	curyear = 20*100+ ((Date.Split.Year /16 * 10) + (Date.Split.Year & 0x0F));

	if(curyear < 2000 || curyear > 2099 )return 0;

	cyear = curyear - 1970;
	cday = cyear/4*(365*3+366);
	
	if(cyear%4 >= 3 )
	{
		cday += (cyear%4-1)*365 + 366;
	}
	else
	{
		cday += (cyear%4)*365;
	}
 
	Mnt = ((Date.Split.Month /16 * 10) + (Date.Split.Month & 0x0F));
	switch(Mnt)
	{
		case  2: curmonthday = 31;  break;
		case  3: curmonthday = 59;  break;
		case  4: curmonthday = 90;  break;
		case  5: curmonthday = 120; break;
		case  6: curmonthday = 151; break;
		case  7: curmonthday = 181; break;
		case  8: curmonthday = 212; break;
		case  9: curmonthday = 243; break;
		case 10: curmonthday = 273; break;
		case 11: curmonthday = 304; break;
		case 12: curmonthday = 334; break;
		default: curmonthday = 0;   break;
	}
	
	if((curyear%4 == 0) && (Mnt >= 3))
	{
		curmonthday+= 1;
	}

	cday += curmonthday;
	cday += ((Date.Split.Day /16 * 10) + (Date.Split.Day & 0x0F)) -1;
	
	day = (cday  + 4) % 7;
	if(!day)day = 7;
	return day;
}

void TDateTime::sDateTimeIncSec(unsigned char *DtBytes, unsigned int IncSec)
{
	TDate aDate;
	TTime aTime;
	unsigned char Hib;
	unsigned char Lowb;
	unsigned int Sec;
	
	Hib = DtBytes[0] /16 *10;
	Lowb = DtBytes[0] %16;
	Hib = Lowb + Hib;
	aDate.Split.Year = Hib;
	aDate.Split.Year += dDATETIME_BASESTART_YEAR;
	Hib = DtBytes[1] /16 * 10;
	Lowb = DtBytes[1] %16;
	Hib = Lowb + Hib;
	aDate.Split.Month = Hib;
	Hib = DtBytes[2] /16 * 10;
	Lowb = DtBytes[2] %16;
	Hib = Lowb + Hib;
	aDate.Split.Day = Hib;
	Hib = DtBytes[3] /16 * 10;
	Lowb = DtBytes[3] %16;
	Hib = Lowb + Hib;
	aTime.Split.Hour = Hib;
	Hib = DtBytes[4] /16 * 10;
	Lowb = DtBytes[4] %16;
	Hib = Lowb + Hib;
	aTime.Split.Minute = Hib;
	Hib = DtBytes[5] /16 * 10;
	Lowb = DtBytes[5] %16;
	Hib = Lowb + Hib;
	aTime.Split.Second = Hib;
	
	sEncodeDateTime(aDate, aTime, &Sec);
	Sec+=IncSec;
	sDecodeDateTime(Sec, &aDate, &aTime);
	
	aDate.Split.Year -= dDATETIME_BASESTART_YEAR;
	Hib = aDate.Split.Year/10 *16;
	Lowb = aDate.Split.Year % 10 + Hib;
	DtBytes[0] = Lowb;
	Hib = aDate.Split.Month/10 *16;
	Lowb = aDate.Split.Month % 10 + Hib;
	DtBytes[1] = Lowb;
	Hib = aDate.Split.Day/10 *16;
	Lowb = aDate.Split.Day % 10 + Hib;
	DtBytes[2] = Lowb;
	Hib = aTime.Split.Hour/10 *16;
	Lowb = aTime.Split.Hour % 10 + Hib;
	DtBytes[3] = Lowb;
	Hib = aTime.Split.Minute/10 *16;
	Lowb = aTime.Split.Minute % 10 + Hib;
	DtBytes[4] = Lowb;
	Hib = aTime.Split.Second/10 *16;
	Lowb = aTime.Split.Second % 10 + Hib;
	DtBytes[5] = Lowb;
}











