/*
 * Date Utility function definitions
 */
 
/*
 * isDateValid() --
 *	to check if the given date is a valid date, return true or false
 *
 *	year	: the number of AD year
 *	month	: the number of month
 *	day		: the number of day
 */
function isDateValid(year, month, day)
{
	var iYear = getInteger(year, 0);
	var iMonth = getInteger(month, 0);
	var iDay = getInteger(day, 0);
	var isValid = true;
	var iMaxDateOfMonth = getMaxPossibleDate(iYear, iMonth);
	
	if (0 == iMaxDateOfMonth)
	{ isValid = false; }
	else if (iDay > iMaxDateOfMonth)
	{ isValid = false; }

	return isValid;
}

/*
 * isLeapYear() --
 *	to check if the given year is a leap year, return true or false
 *
 *	year	: the number of AD year
 */
function isLeapYear(year)
{
	var iYear = getInteger(year, 0);
	var isLeap = false;
	
	if (0 < iYear)
	{
		if (0 == iYear % 400)
		{ isLeap = true; }
		else if (0 == iYear % 100)
		{ isLeap = false; }
		else if (0 == iYear % 4)
		{ isLeap = true; }
		else
		{ isLeap = false; }
    }
   
	return isLeap;
}

/*
 * getMaxPossibleDate() --
 *	to return the number of days (as an integer) for the given year and month.
 *	If the given year and month is not valid, 0 is returned
 *
 *	year	: the number of AD year
 *	month	: the number of month
 */
function getMaxPossibleDate(year, month)
{
	var iYear = getInteger(year, 0);
	var iMonth = getInteger(month, 0);
	var iMaxDateOfMonth;
	switch(iMonth)
    {
		case 1:
		case 3:
		case 5:
		case 7:
		case 8:
		case 10:
		case 12:
			iMaxDateOfMonth = 31;
			break;
		case 4:
		case 6:
		case 9:
		case 11:
			iMaxDateOfMonth = 30;
			break;
		case 2:
			if (true == isLeapYear(iYear))
			{ iMaxDateOfMonth = 29; }
			else
			{ iMaxDateOfMonth = 28; }
			break;
		default:
			iMaxDateOfMonth = 0;
			break;
	}
	return iMaxDateOfMonth;
}

/*
 * getClosedDateLessThan() --
 *	to get the max date, in Date obj format, less than or equal to the 
 *	given date
 *
 *	year	: the number of AD year
 *	month	: the number of month
 *	day		: the number of day
 */
function getClosedDateLessThan(year, month, day)
{
	var iYear = getInteger(year, getCurrentYear());
	var iMonth = getInteger(month, getCurrentMonth());
	var iDay = getInteger(day, getCurrentDay());
	
	while (!isDateValid(iYear, iMonth, iDay))
	{
		--iDay;
		if (0 >= iDay)
		{
			--iMonth;
			if (0 >= iMonth)
			{
				--iYear;
				iMonth = 12;
			}
			iDay = getMaxPossibleDate(iYear, iMonth);
		}
	} //end while
	
	return new Date(iYear, iMonth-1, iDay);
}

/*
 * getClosedDateGreaterThan() --
 *	to get the min date, in Date obj format, greater than or equal to the 
 *	given date
 *
 *	year	: the number of AD year
 *	month	: the number of month
 *	day		: the number of day
 */
function getClosedDateGreaterThan(year, month, day)
{
	var iYear = getInteger(year, getCurrentYear());
	var iMonth = getInteger(month, getCurrentMonth());
	var iDay = getInteger(day, getCurrentDay());
	
	while (!isDateValid(iYear, iMonth, iDay))
	{
		++iDay;
		if (getMaxPossibleDate(iYear, iMonth) > iDay)
		{
			++iMonth;
			if (12 < iMonth)
			{
				++iYear;
				iMonth = 1;
			}
			iDay = 1;
		}
	} //end while
	
	return new Date(iYear, iMonth-1, iDay);
}

/*
 * getDateAfterDays() --
 *	to return the date, in Date object format, which is 'numOfDays' later
 *	than the given date
 *
 *	year		: the number of AD year
 *	month		: the number of month
 *	day			: the number of day
 *	numOfDays	: number of days later
 */
function getDateAfterDays(year, month, day, numOfDays)
{
	var iYear = getInteger(year, getCurrentYear());
	var iMonth = getInteger(month, getCurrentMonth());
	var iDay = getInteger(day, getCurrentDay());
	var iNumOfDays = getInteger(numOfDays);
	
	var dateBase = new Date(iYear, iMonth-1, iDay);
	var iAfter = iNumOfDays * 24 * 60 * 60 * 1000;
	return new Date(dateBase.getTime() + iAfter);
}

/*
 * getDateAfterMonths() --
 *	to return the date, in Date object format, which is 'numOfMonths' later
 *	than the given date
 *
 *	year		: the number of AD year
 *	month		: the number of month
 *	day			: the number of day
 *	numOfMonths	: number of months later
 */
function getDateAfterMonths(year, month, day, numOfMonths)
{
	var iYear = getInteger(year, getCurrentYear());
	var iMonth = getInteger(month, getCurrentMonth());
	var iDay = getInteger(day, getCurrentDay());
	iMonth += getInteger(numOfMonths);
	
	while (iMonth >= 12)
	{
		iMonth -= 12;
		++iYear;
	}
	
	while (iMonth <= 0)
	{
		iMonth += 12;
		--iYear;
	}
	
	return new Date(iYear, iMonth-1, iDay);
}

/*
 * getDateBeforeDays() --
 *	to return the date, in Date object format, which is 'numOfDays' earlier
 *	than the given date
 *
 *	year		: the number of AD year
 *	month		: the number of month
 *	day			: the number of day
 *	numOfDays	: number of days later
 */
function getDateBeforeDays(year, month, day, numOfDays)
{
	return getDateAfterDays(year, month, day, (-1) * getInteger(numOfDays));
}

/*
 * getDateBeforeMonths() --
 *	to return the date, in Date object format, which is 'numOfMonths' earlier
 *	than the given date
 *
 *	year		: the number of AD year
 *	month		: the number of month
 *	day			: the number of day
 *	numOfMonths	: number of months later
 */
function getDateBeforeMonths(year, month, day, numOfMonths)
{
	return getDateAfterMonths(year, month, day, (-1) * getInteger(numOfMonths));
}

/*
 * getCurrentYear() --
 *	to return the current AD year (4-digits)
 */
function getCurrentYear()
{
	return new Date().getFullYear();
}

/*
 * getCurrentMonth() --
 *	to return the current month (1 to 12)
 */
function getCurrentMonth()
{
	return (new Date().getMonth()) + 1;
}

/*
 * getCurrentDay() --
 *	to return the current day (1 to 31)
 */
function getCurrentDay()
{
	return new Date().getDate();
}