//////////////////////////////////////////////////////////////////////////////////////////////////
//																								//
//											NCDate                 	                     		//
//										  Tony Payne											//
//										July 14, 1998											//
//																								//
//////////////////////////////////////////////////////////////////////////////////////////////////
//
//
//
//	This function returns a specialized Date object.  You can think of it almost as
//	a child class of Date.  This is done by creating a Date object, assigning new
//	properties and methods to it, and returning that Date object.
//
//	usage:
//		var ncdateToday = NCDate();						//Returns current date
//		var ncdateChristmas = NCDate(1998, 12, 25);
//
//
//	Differences from the normal Date object:
//
//		Months go from 1-12.
//
//		All years are 4-digit.  The normal Date object uses 2 digits for 1900-1999 (00-99).
//
//		Method names begin with capital letters.  This is important, because using the old
//			style names, will actually call the original methods, which use the old
//			numbering schemes.
//
//		Added new methods.
//
//			GetWeekdayName()		returns a string containing the name of the day of
//									the week.
//
//			GetMonthName()			returns a string containing the name of the month.
//
//			CompareDate(dateToComp)	returns an integer which is positive if the parameter
//									represents a future date.  Returns negative if the
//									parameter represents a past date.  Returns zero if the
//									parameter represents the same date.
//
//			IsFutureDate(dateComp)	returns true if dateComp is a future date.  returns
//									false otherwise.		
//
//			IsPastDate(dateToComp)	returns true if dateToComp is a past date.  returns
//									false otherwise.
//
//			IsSameDate(dateToComp)	returns true if dateToComp represents the same date.
//									returns false otherwise.
//
//			IsLeapYear()			returns true if this date lies in a leap year.
//
//			GetDaysThisMonth()		returns the number of days in this month.
//
//			IsValidDate()			returns true if the date exists.  Checks to make sure
//									the date exists in the month.  Checks for Febrary dates
//									in leap year.
//
//			AddDate(dateToAdd)		adds the specified date to this one and returns a new
//									NCDate with the specified date.  Usually used to add
//									a timespan to the current date.  The following NCDate
//									constants can be used to create a timespan.
//										NCDate.SECOND, NCDate.MINUTE, NCDate.HOUR,
//										NCDate.DAY, NCDate.WEEK
//									usage:
//										var ncdateToday = NCDate();
//										var ncdateWeek = NCDate(ncdateToday.WEEK);
//										var ncdateNextWeek = ncdateToday.AddDate(ncdateWeek);
//									alternate method:
//										var ncdateNextWeek = NCDate();
//										ncdateNextWeek.SetDate(ncdateNextWeek.GetDate() + 7);
//									The alternate method works because the NCDate object wraps
//									around any date or month that is too large.  So, even if 
//									GetDate() returned 27, the result will be correct.
//
//			SubtractDate(dateToSub)	Subtracts the date (or timespan) from this NCDate.
//
//			GetAgeAt(dateAtWhich)	Assuming this NCDate represents a birthdate, returns the
//									age (in years) of the person on the specified date.
//									usage:
//										var ncdateBirthday = NCDate(1977, 10, 10);
//										var iAge = ncdateBirthday.GetAgeAt(NCDate());
//
//	Constants
//
//			SECOND		1000 milliseconds.  One second.
//			MINUTE		1 minute
//			HOUR		1 hour
//			DAY			1 day
//			WEEK		1 week
//			MONTH		same as GetDaysThisMonth()
//			YEAR		if this is a leap year, 366 else 365
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////

function NCDate()
{
	var RetDate;
	switch(NCDate.arguments.length)
	{

		case 0:
			RetDate = new Date();
			break;

		case 1:	
			RetDate = new Date(NCDate.arguments[0]);
			break;

		case 3:
			RetDate = new Date(	NCDate.arguments[0],
								NCDate.arguments[1] - 1,		//Allow month 1-12
								NCDate.arguments[2]);				
			RetDate.IsValid = NCIsValidDate(	NCDate.arguments[0],
								NCDate.arguments[1],
								NCDate.arguments[2]);
			break;

		case 6:
			RetDate = new Date(	NCDate.arguments[0],
								NCDate.arguments[1] - 1,		//Allow month 1-12
								NCDate.arguments[2],				
								NCDate.arguments[3],				   			
								NCDate.arguments[4],			
						   		NCDate.arguments[5]);
			RetDate.IsValid = NCIsValidDate(	NCDate.arguments[0],
								NCDate.arguments[1],
								NCDate.arguments[2]);
			break;
		
		default:
			return null;

	}
	
	//returns String name of Day of Week
	RetDate.GetWeekdayName = function()
				 {
					var aszWeekdayNames = [	"Sunday",
											"Monday",
											"Tuesday",
											"Wednesday",
											"Thursday",
											"Friday",
											"Saturday"
										  ];
					return aszWeekdayNames[this.getDay()];
				};
				
	//returns String name of Month				
	RetDate.GetMonthName =  function()
				{
					var aszMonthNames = [ 	"January",
											"February",
											"March",
											"April",
											"May",
											"June",
											"July",
											"August",
											"September",
											"October",
											"November",
											"December"
									   ];
					return aszMonthNames[this.getMonth()];
				};
	
	// Adjusts month to fall between 1 and 12			
	RetDate.GetMonth = 	function()
				{
					return this.getMonth() + 1;
				};
				
	// Adjusts month to make 1-12 valid (Date requires 0-11)				
	RetDate.SetMonth = 	function(iMonth)
				{
					this.setMonth(iMonth-1);
				};
				
	RetDate.GetTime =	function()
				{
					return this.getTime();
				};
	
	//converts all years to 4 digits
	RetDate.GetYear = 	function()
				{
					var iYear = this.getYear();
					if(iYear < 100) iYear += 1900;
					return iYear;
				};
				
	RetDate.GetDate = 	function()
				{
					return this.getDate();
				};
	
	RetDate.GetDay = 	function()
				{
					return this.getDay();
				};
				
	RetDate.GetHours = 	function()
				{
					return this.getHours();
				};
				
	RetDate.GetMinutes = 	function()
				{
					return this.getMinutes();
				};
	
	RetDate.GetSeconds = 	function()
				{
					return this.getSeconds();
				};
				
	RetDate.SetTime =	function(fTime)
				{
					this.setTime(fTime);
				};
				
	RetDate.SetYear = 	function(iYear)
				{
					if(iYear < 100) iYear += 1900;
					this.setYear(iYear);
				};
	
	RetDate.SetDate = 	function(iDate)
				{
					this.setDate(iDate);
				};
				
	RetDate.SetDay = 	function(iDay)
				{
					this.setDay(iDay);
				};
	
	RetDate.SetHours = 	function(iHours)
				{
					this.setHours(iHours);
				};
				
	RetDate.SetMinutes = 	function(iMinutes)
				{
					this.setMinutes(iMinutes);
				};
				
	RetDate.SetSeconds = 	function(iSeconds)
				{
					this.setSeconds(iSeconds);
				};
				

	//Returns positive if the parameter is in the future, negative if in the past and zero if same.
	RetDate.CompareDate =	function(dateCompare)
				{
					if(!NCTypeOf(dateCompare, "Date"))
						return "NOT A DATE";
						
					var iYearDiff = dateCompare.GetYear() - this.GetYear();
					if(iYearDiff != 0)
						return iYearDiff;
					
					var iMonthDiff = dateCompare.GetMonth() - this.GetMonth();
					if(iMonthDiff !=0)
						return iMonthDiff;
						
					var iDateDiff = dateCompare.GetDate() - this.GetDate();
					return iDateDiff;
				};
				
	//returns boolean
	RetDate.IsFutureDate = 	function(dateCompare)
				{
					return (this.CompareDate(dateCompare) > 0);
				};

	//returns boolean				
	RetDate.IsPastDate = 	function(dateCompare)
				{
					return (this.CompareDate(dateCompare) < 0);
				};

	//returns boolean				
	RetDate.IsSameDate = 	function(dateCompare)
				{
					return (this.CompareDate(dateCompare) == 0);
				};

	//returns boolean
	RetDate.IsLeapYear = 	function()
				{
					return NCIsLeapYear(this.getYear());
				};

	RetDate.GetDaysThisMonth = function()
				{
					return NCGetDaysInMonth(this.getMonth(), this.getYear());
				}

	//returns boolean				
	RetDate.IsValidDate =	function()
				{
					return NCIsValidDate(this.getYear(), this.getMonth(), this.getDate());
				};

	//returns new NCDate
	RetDate.AddDate =	function(dateToAdd)
				{
					return NCDate(dateToAdd.getTime() + this.getTime());
				};
				
	//returns new NCDate				
	RetDate.SubtractDate =	function(dateToSubtract)
				{
					return NCDate(this.getTime() - dateToSubtract.getTime());
				};
				
	//returns integer. This NCDate object is treated like a "birthday" and the
	//		functions returns the "age" someone or something would be on the specified
	//		date.
	RetDate.GetAgeAt = 	function(dateAtWhich)
				{
					var ncdateAtWhich = NCDate(dateAtWhich.getTime());
					var iYearDiff = ncdateAtWhich.GetYear() - this.GetYear();
					var iMonthDiff = this.GetMonth() - ncdateAtWhich.GetMonth();
					if(iMonthDiff < 0)
						return iYearDiff - 1;
					if(iMonthDiff > 0)
						return iYearDiff;
					
					var iDayDiff = this.GetDate() - ncdateAtWhich.GetDate();
					if(iDayDiff < 0)
						return iYerDiff - 1;
					return iYearDiff;
				};
				
	RetDate.WasConstructorDateValid = function()
				{
					return this.IsValid;
				}
				
	//constants.  These are the timespans of various time segments in milliseconds
	RetDate.SECOND = 1000;
	RetDate.MINUTE = 60 * RetDate.SECOND;
	RetDate.HOUR   = 60 * RetDate.MINUTE;
	RetDate.DAY    = 24 * RetDate.HOUR;
	RetDate.WEEK   = 7 * RetDate.DAY;
	RetDate.MONTH  = RetDate.GetDaysThisMonth();
	RetDate.YEAR   = RetDate.IsLeapYear() ? 366 : 365;
					
	return RetDate;	
}

function NCIsLeapYear(iYear)
{
	return ( ( ((iYear % 400) == 0)     ||
			 ( ((iYear % 4) == 0) && ((iYear % 100) != 0)) ) );
}

function NCGetDaysInMonth(iMonth, iYear)
{
	var aiDaysInMonths = [31,28,31,30,31,30,31,31,30,31,30,31];
	if(iMonth != 2)
		return aiDaysInMonths[iMonth];
	else if(NCIsLeapYear(iYear))
		return 29;
	else
		return 28;
}

function NCIsValidDate(iYear, iMonth, iDate)
{
	if(iMonth < 1 || iMonth > 12 || iDate < 1)
		return false; 
	if(iDate > NCGetDaysInMonth(iMonth, iYear))
		return false;
	return true;
}