/* DatePrototype
Author:		Frazer McCormack
Date:		19-Mar-2003
Version:	1.2.0 
functions:
closestMondayToMonth()		- return the closest monday before the month provided
dateAdd(i_strInterval,i_lngNumber,i_blnCopy)
	i_strInterval can be:  's','n','h','d','m','y' which relate to second, minutes, hours, days, months, years respectivly
	i_lngNumber can be any whole number that will keep the result within 285,616 years +/- of the orignal date
	i_blnCopy is an optional parameter.  Pass 'true' to return the result in a new variable.  Pass anything else or nothing to modify the passed date 
format(i_strFormat)
	i_strFormat	- a string containing 1 from any or all of the following groups:  years(yy,yyyy), months(m,mm,mmm,mmmm), days(d,dd), weekday(w,ww,www,wwww), hours(h,hh), minutes(n,nn), seconds(s,ss)
*/
//////////////////////////////////////////////////////////////////////////////
//DECLARATIONS
//////////////////////////////////////////////////////////////////////////////
Date.prototype.closestMondayToMonth=closestMondayToMonth;
Date.prototype.dateAdd=dateAdd;
Date.prototype.format=format;
//////////////////////////////////////////////////////////////////////////////
//END OF DECLARATIONS
//////////////////////////////////////////////////////////////////////////////


//////////////////////////////////////////////////////////////////////////////
//START OF PROTOTYPES
//////////////////////////////////////////////////////////////////////////////
function closestMondayToMonth()
{
	var dteFirstDayOfMonth=new Date(new Number(this.format('yyyy')),new Number(this.format('m'))-1,1);
	dteFirstDayOfMonth=dteFirstDayOfMonth.dateAdd('n',-dteFirstDayOfMonth.getTimezoneOffset(),true);
	return dteFirstDayOfMonth.dateAdd('d',-dteFirstDayOfMonth.getUTCDay()+1,true);
}

function dateAdd(i_strInterval,i_lngNumber,i_blnCopy)
{
	if(i_blnCopy&&(i_blnCopy==true||i_blnCopy=='true'))
		var dteNew=new Date(this);
	switch(i_strInterval)
	{
		case 's':	//seconds
			if(i_blnCopy&&(i_blnCopy==true||i_blnCopy=='true'))
				dteNew.setSeconds(this.getSeconds()+i_lngNumber);
			else
				this.setSeconds(this.getSeconds()+i_lngNumber);
			break;
		case 'n':	//minutes
			if(i_blnCopy&&(i_blnCopy==true||i_blnCopy=='true'))
				dteNew.setMinutes(this.getMinutes()+i_lngNumber);
			else
				this.setMinutes(this.getMinutes()+i_lngNumber);
			break;
		case 'h':	//hours
			if(i_blnCopy&&(i_blnCopy==true||i_blnCopy=='true'))
				dteNew.setHours(this.getHours()+i_lngNumber);
			else
				this.setHours(this.getHours()+i_lngNumber);
			break;
		case 'd':	//days
			if(i_blnCopy&&(i_blnCopy==true||i_blnCopy=='true'))
				dteNew.setDate(this.getDate()+i_lngNumber);
			else
				this.setDate(this.getDate()+i_lngNumber);
			break;
		case 'm':	//months
			if(i_blnCopy&&(i_blnCopy==true||i_blnCopy=='true'))
				dteNew.setMonth(this.getMonth()+i_lngNumber);
			else
				this.setMonth(this.getMonth()+i_lngNumber);
			break;
		case 'y':	//years
			if(i_blnCopy&&(i_blnCopy==true||i_blnCopy=='true'))
				dteNew.setFullYear(this.getFullYear()+i_lngNumber);
			else
				this.setFullYear(this.getFullYear()+i_lngNumber);
			break;
		default:
			throw {description:'Interval type not supported'}
	}
	if(i_blnCopy&&(i_blnCopy==true||i_blnCopy=='true'))
		return dteNew;
	else
		return this;
}

function format(i_strFormat)
{	
	var strDayFormat=void 0;
	var strWeekdayFormat=void 0;
	var strMonthFormat=void 0;
	var strYearFormat=void 0;
	var strHourFormat=void 0;
	var strMinuteFormat=void 0;
	var strSecondFormat=void 0;
	
	//take off any utc timezone gaps that will knock the correct formats out.
	var tmpDate=this.dateAdd('n',-this.getTimezoneOffset(),true);

	if(i_strFormat.match(/dd/)!= void 0)
		strDayFormat='dd';
	else if(i_strFormat.match(/d/)!= void 0)
		strDayFormat='d';

	if(i_strFormat.match(/mmmm/)!= void 0)
		strMonthFormat='mmmm';
	else if(i_strFormat.match(/mmm/)!= void 0)
		strMonthFormat='mmm';
	else if(i_strFormat.match(/mm/)!= void 0)
		strMonthFormat='mm';
	else if(i_strFormat.match(/m/)!= void 0)
		strMonthFormat='m';
		
	if(i_strFormat.match(/wwww/)!= void 0)
		strWeekdayFormat='wwww';
	else if(i_strFormat.match(/www/)!= void 0)
		strWeekdayFormat='www';
	else if(i_strFormat.match(/ww/)!= void 0)
		strWeekdayFormat='ww';
	else if(i_strFormat.match(/w/)!= void 0)
		strWeekdayFormat='w';
	
	if(i_strFormat.match(/yyyy/)!= void 0)
		strYearFormat='yyyy';
	else if(i_strFormat.match(/yy/)!= void 0)
		strYearFormat='yy';
		
	if(i_strFormat.match(/hh/)!= void 0)
		strHourFormat='hh';
	else if(i_strFormat.match(/h/)!= void 0)
		strHourFormat='h';		
		
	if(i_strFormat.match(/nn/)!= void 0)
		strMinuteFormat='nn';
	else if(i_strFormat.match(/n/)!= void 0)
		strMinuteFormat='n';	
		
	if(i_strFormat.match(/ss/)!= void 0)
		strSecondFormat='ss';
	else if(i_strFormat.match(/s/)!= void 0)
		strSecondFormat='s';					
	
	var lngDay=tmpDate.getUTCDate();
	var strDay='';	
	switch(strDayFormat)
	{
		case 'd':
			strDay=lngDay.toString();
			break;
		case 'dd':
			strDay=(lngDay.toString().length==1?'0'+lngDay.toString():lngDay).toString();
			break;
	}
	
	var lngWeekday=tmpDate.getUTCDay();
	var strWeekday='';
	switch(strWeekdayFormat)
	{
		case 'w':
			strWeekday=(lngWeekday+1).toString();
			break;
		case 'ww':
			strWeekday=((lngWeekday+1).toString().length==1?'0'+(lngWeekday+1).toString():lngWeekday+1).toString();
			break;
		case 'www':
			switch(lngWeekday)
			{
				case 0:
					strWeekday='Sun';
					break;
				case 1:
					strWeekday='Mon';
					break;				
				case 2:
					strWeekday='Tue'
					break;				
				case 3:
					strWeekday='Wed'
					break;				
				case 4:
					strWeekday='Thu'
					break;				
				case 5:
					strWeekday='Fri'
					break;				
				case 6:
					strWeekday='Sat'
					break;				
			}
			break;
		case 'wwww':
			switch(lngWeekday)
			{
				case 0:
					strWeekday='Sunday';
					break;
				case 1:
					strWeekday='Monday';
					break;				
				case 2:
					strWeekday='Tuesday'
					break;				
				case 3:
					strWeekday='Wednesday'
					break;				
				case 4:
					strWeekday='Thursday'
					break;				
				case 5:
					strWeekday='Friday'
					break;				
				case 6:
					strWeekday='Saturday'
					break;				
			}
			break;
	}
	
	var lngMonth=tmpDate.getUTCMonth();
	var strMonth='';
	switch(strMonthFormat)
	{
		case 'm':
			strMonth=(lngMonth+1).toString();
			break;
		case 'mm':
			strMonth=((lngMonth+1).toString().length==1?'0'+(lngMonth+1).toString():lngMonth+1).toString();
			break;
		case 'mmm':
			switch(lngMonth)
			{
				case 0:
					strMonth='Jan';
					break;
				case 1:
					strMonth='Feb';
					break;
				case 2:
					strMonth='Mar';
					break;
				case 3:
					strMonth='Apr';
					break;
				case 4:
					strMonth='May';
					break;
				case 5:
					strMonth='Jun';
					break;
				case 6:
					strMonth='Jul';
					break;
				case 7:
					strMonth='Aug';
					break;
				case 8:
					strMonth='Sep';
					break;
				case 9:
					strMonth='Oct';
					break;
				case 10:
					strMonth='Nov';
					break;
				case 11:
					strMonth='Dec';
					break;
			}
			break;
		case 'mmmm':
			switch(lngMonth)
			{
				case 0:
					strMonth='January';
					break;
				case 1:
					strMonth='February';
					break;
				case 2:
					strMonth='March';
					break;
				case 3:
					strMonth='April';
					break;
				case 4:
					strMonth='May';
					break;
				case 5:
					strMonth='June';
					break;
				case 6:
					strMonth='July';
					break;
				case 7:
					strMonth='August';
					break;
				case 8:
					strMonth='September';
					break;
				case 9:
					strMonth='October';
					break;
				case 10:
					strMonth='November';
					break;
				case 11:
					strMonth='December';
					break;
			}		
			break;
	}

	var lngYear=tmpDate.getUTCFullYear();
	var strYear='';	
	switch(strYearFormat)
	{
		case 'yy':
			strYear=lngYear.toString().substring(2);
			break;
		case 'yyyy':
			strYear=lngYear.toString();
			break;
	}
	
	var lngHour=tmpDate.getUTCHours();
	var strHour='';	
	switch(strHourFormat)
	{
		case 'h':
			strHour=lngHour.toString();
			break;
		case 'hh':
			strHour=(lngHour.toString().length==1?'0'+lngHour.toString():lngHour).toString();
			break;
	}
	
	var lngMinute=tmpDate.getUTCMinutes();
	var strMinute='';	
	switch(strMinuteFormat)
	{
		case 'n':
			strMinute=lngMinute.toString();
			break;
		case 'nn':
			strMinute=(lngMinute.toString().length==1?'0'+lngMinute.toString():lngMinute).toString();
			break;
	}
	
	var lngSecond=tmpDate.getUTCSeconds();
	var strSecond='';	
	switch(strSecondFormat)
	{
		case 's':
			strSecond=lngSecond.toString();
			break;
		case 'ss':
			strSecond=(lngSecond.toString().length==1?'0'+lngSecond.toString():lngSecond).toString();
			break;
	}
	
	var strTmp=i_strFormat.replace(strDayFormat,strDay);
	strTmp=strTmp.replace(strMonthFormat,strMonth);
	strTmp=strTmp.replace(strYearFormat,strYear);
	strTmp=strTmp.replace(strHourFormat,strHour);
	strTmp=strTmp.replace(strMinuteFormat,strMinute);
	strTmp=strTmp.replace(strSecondFormat,strSecond);
	strTmp=strTmp.replace(strWeekdayFormat,strWeekday);

	return strTmp;
}
//////////////////////////////////////////////////////////////////////////////
//END OF PROTOTYPES
//////////////////////////////////////////////////////////////////////////////


//////////////////////////////////////////////////////////////////////////////
//PRIVATE FUNCTIONS
//////////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////////
//END OF PRIVATE FUNCTIONS
//////////////////////////////////////////////////////////////////////////////