function zeroPad(pad, num) {
	var sNum = num.toString();
	while (sNum.length < pad)
		sNum = '0' + sNum;
	if (pad==1)
		return sNum;
	else
		return sNum.substr(sNum.length-pad);
}

/*
*********************************************************************************************************************************
				Start of Date Object additions
*********************************************************************************************************************************
				
=================================================================
 isDST
	Parameters: NONE 

	returns: true/false on whether or not the date object date is in U.S. Daylight savings time
			(1st Sunday in April - last Sunday in October)

=================================================================
*/
Date.prototype.isDST = function () {
	if ((this.getMonth() < 2) || (this.getMonth() > 10))
		return false;

	if ((this.getMonth() >2) && (this.getMonth() < 11))
		return true;


	if (this.getMonth() == 2) {
		var secondSundayInMarch = new Date('3/1/' + this.getFullYear());
		return (this.getDay()>(14-secondSundayInMarch.getDay()))
	}

	// we know we are in November. Get the day # of the FIRST sunday
	var firstSundayInNovember = new Date(this.toString());
	firstSundayInNovember.setDate(7);
	firstSundayInNovember.setDate((7 - firstSundayInNovember.getDay()));
	return (firstSundayInNovember <= this)
} 

/*
=================================================================
 isLeapYear
	Parameters: y = Year. Must be full year (yyyy). 

	returns: true/false

 Notes: Function is only valid back to 1582 due to calander changes prior to this date
=================================================================
*/
Date.prototype.isLeapYear = function () {
	var leapYear = false;
	if (this.getFullYear()%4 == 0) {
		leapYear = true;
		if (this.getFullYear()%100 == 0) {
			leapYear = false;
			if (this.getFullYear()%400 == 0) {
				leapYear = true;
			}
		}
	}

	return leapYear;
}

/*
=================================================================
 daysInMonth
	Parameters: None

	returns: Number of days in the date object set month

 Notes: Function is only valid back to 1582 due to calander changes prior to this date
=================================================================
*/
Date.prototype.daysInMonth = function () {
	var numDays = 0;
	switch (this.getMonth()+1) {
		case 4:
		case 6:
		case 9:
		case 11:	
			numDays = 30;
			break;
		case 2:	
			numDays = (this.isLeapYear())? 29: 28;
			break;

		default:	
			numDays = 31;
			break;
	}
	return numDays;
}

/*
=================================================================
 dateAdd
	Parameters: 
		strInterval: a string constant of what interval to add to the date. Valid Intervals are -
			Interval | Description
			---------+------------
			   year  | Year
			 quarter | Quarter
			   month | Month
			   week  | Week
			   day   | Day 
			  weekday| Weekday
		   weekendday| Weekend day
			    hour | Hour
			 minute  | Minute
			 second  | Second
			    ms   | Millisecond
		intNumber: denotes the number of strIntervals to add (may be a negative number)

	returns: the new date

 Notes: Function will change its own date AND is only valid back to 1582 due to calander changes prior to this date
=================================================================
*/
Date.prototype.dateAdd = function (strInterval, intNumber) {
	intNumber = Math.floor(intNumber);
	var direction = (intNumber < 0)?-1:1;
	var posInt = intNumber * direction;

	if (intNumber!=0)
		switch(strInterval.toLowerCase()) {
			case 'year': {
					var oldMonth = this.getMonth();
					this.setFullYear(this.getFullYear() + intNumber);
					while (this.getMonth() > oldMonth) // 2/29/2000 <> 3/1/2001!!!
						this.setMilliseconds(this.getMilliseconds() - (1000*60*60*24)); // drop 1 day
					break;
						}
			case 'quarter': {
					var nextQMonth = this.getMonth() + (3*intNumber);
					while (nextQMonth>11 || nextQMonth<0) {
						this.setFullYear(this.getFullYear() + direction);
						nextQMonth = nextQMonth - (12 * direction);
					}

					this.setMonth(nextQMonth);

					while (this.getMonth() != nextQMonth) 
						this.setMilliseconds(this.getMilliseconds() - (1000*60*60*24*direction)); 
					break;
						}
			case 'month': {
					var nextMonth = this.getMonth() + intNumber;
					while (nextMonth>11 || nextMonth<0) {
						this.setFullYear(this.getFullYear() + direction);
						nextMonth = nextMonth - (12 * direction);
					}

					this.setMonth(nextMonth);

					while (this.getMonth() != nextMonth) // 2/29/2000 <> 3/1/2001!!!
						this.setMilliseconds(this.getMilliseconds() - (1000*60*60*24*direction)); // drop 1 day
					break;
						}
			case 'week': {
					this.setMilliseconds(this.getMilliseconds() + (1000*60*60*24*7*intNumber)); // move # weeks (7 day groups)
					break;
						}
			case 'weekday': {
					for(var i = (intNumber * direction); i > 0; i--)
						do {
							this.setMilliseconds(this.getMilliseconds() + (1000*60*60*24*direction)); // move 1 weekday
							} while(this.getDay()==0 || this.getDay()==6)
					break;
						}
			case 'weekendday': {
					for(var i = (intNumber * direction); i > 0; i--)
						do {
							this.setMilliseconds(this.getMilliseconds() + (1000*60*60*24*direction)); // move 1 weekday
							} while(this.getDay()!=0 && this.getDay()!=6)
					break;
						}
			case 'day': {
					this.setMilliseconds(this.getMilliseconds() + (1000*60*60*24*intNumber)); // move # days
					break;
						}
			case 'hour': {
					this.setMilliseconds(this.getMilliseconds() + (1000*60*60*intNumber)); // move # hours
					break;
						}
			case 'minute': {
					this.setMilliseconds(this.getMilliseconds() + (1000*60*intNumber)); // move # minutes
					break;
						}
			case 'second': {
					this.setMilliseconds(this.getMilliseconds() + (1000*intNumber)); // move # secs
					break;
						}
			case 'ms': {
					this.setMilliseconds(this.getMilliseconds() + (intNumber)); // move # ms
					break;
						}
		}
	return this;
}


/*
=================================================================
 getFDate
	Parameters: (all optional)
		strFormat: the format to return the date in.
		strTimeZoneAbv: Time Zone abv to place in the formatted date (if the format required it)
		fGMTOffSet: The gmt offset IN MINUTES of the timezoneabv. (used to display the date/time at this given GMT Offset, but does NOT change the actual date stored in the object)
	returns: The Date formatted

 Notes: Function will default to format of getDate function if format info is not set. If strTimeZoneAbv is passed
 	and not the GMTOffset the function will ignore the timezoneabv.
 	
 	Date formatting:
	All SINGLE letters maybe repeated to force a digit [single letter will occupy all digits] (aka on a year of 2001: y=2001, yy=01, yyy=001, yyyy=2001, yyyyy=02001)
	Allowed letters:
	YYYY	year
	YY	year
	M	month
	MM	month
	mm	full month name (January)
	m	abv. month name (Jan)
	D	day
	DD	day
	ww	full day name (Wednesday)
	w	abv. day name (Wed)
	H	standard hour (1-12)
	HH	standard hour (1-12)
	I	military hour (0-23)
	II	military hour (0-23)
	N	minutes
	NN	minutes
	S	seconds
	SS	seconds
	am	meridiem specifier (am/pm)
	tz	timezone

	al other characters are passed through and ignored
	
	Based on 1:15:30 pm 3/29/2000 the following formats will do:
	
	I:N ww, mm D, YYYY	=	13:15 Wednesday, March 29, 2000
	
	HH:N am (tz)		=	01:15 pm (CT)

=================================================================
*/
Date.prototype.getFDate = function (strFormat, strTimeZoneAbv, fGMTOffSet, sDefault) {
	if (strFormat==null)
		return this.toString();
	if (strTimeZoneAbv==null)
		strTimeZoneAbv = 'ct';
		
	if (fGMTOffSet==null) 
		fGMTOffSet = 0;
		
	if (sDefault==null)
		sDefault='';
		
	var dayNames = new Array;
	dayNames[0] = 'Sunday';
	dayNames[1] = 'Monday';
	dayNames[2] = 'Tuesday';
	dayNames[3] = 'Wednesday';
	dayNames[4] = 'Thursday';
	dayNames[5] = 'Friday';
	dayNames[6] = 'Saturday';
	
	var monthNames = new Array;
	monthNames[0] = 'January';
	monthNames[1] = 'February';
	monthNames[2] = 'March';
	monthNames[3] = 'April';
	monthNames[4] = 'May';
	monthNames[5] = 'June';
	monthNames[6] = 'July';
	monthNames[7] = 'August';
	monthNames[8] = 'September';
	monthNames[9] = 'October';
	monthNames[10] = 'November';
	monthNames[11] = 'December';

	var fDate = new Date(this);
	
	if (isNaN(fDate))
		return sDefault;
		
	if (fGMTOffSet!=0) {
		fDate.setMilliseconds(fDate.getMilliseconds() + (1000*60*this.getTimezoneOffset()));
		fDate.setMilliseconds(fDate.getMilliseconds() + (1000*60*fGMTOffSet));
	}

	var retVal = '';
	var idx = 0;
	while (idx < strFormat.length) {
		var aMatch = strFormat.substr(idx).match(/^(Y+|M+|m{1,2}|D+|w{1,2}|H+|I+|N+|S+|am|tz)/);
		if (aMatch==null)
			retVal += strFormat.charAt(idx++);
		else {
			switch (aMatch[1].charAt(0)) {
				case 'm':
					if (aMatch[1].length==2)
						retVal += aMatch[1].replace(/^mm$/, monthNames[fDate.getMonth()]);
					else
						retVal += aMatch[1].replace(/^m$/, monthNames[fDate.getMonth()].substring(0,3));
					break;
					
				case 'w':
					if (aMatch[1].length==2)
						retVal += aMatch[1].replace(/^ww$/, dayNames[fDate.getDay()]);
					else
						retVal += aMatch[1].replace(/^w$/, dayNames[fDate.getDay()].substring(0,3));
					break;
					
				case 'a':
					retVal += (fDate.getHours() > 11)?'pm':'am';
					break;

				case 'Y':
					retVal += zeroPad(aMatch[1].length, fDate.getFullYear());
					break;

				case 'M':
					retVal += zeroPad(aMatch[1].length, fDate.getMonth()+1);
					break;

				case 'D':
					retVal += zeroPad(aMatch[1].length, fDate.getDate());
					break;

				case 'H':
					var hour = (fDate.getHours()==0)?12:fDate.getHours();
					hour = (hour>12)?hour-12:hour;
					retVal += zeroPad(aMatch[1].length, hour);
					break;

				case 'I':
					retVal += zeroPad(aMatch[1].length, fDate.getHours());
					break;

				case 'N':
					retVal += zeroPad(aMatch[1].length, fDate.getMinutes());
					break;

				case 'S':
					retVal += zeroPad(aMatch[1].length, fDate.getSeconds());
					break;

				case 'N':
					retVal += zeroPad(aMatch[1].length, fDate.getMinutes());
					break;

				case 't':
					retVal += strTimeZoneAbv.toUpperCase();
					break;
					
				default:
					retVal += aMatch[1]; // no clue what happened
					break;
			} // switch
			
			idx += aMatch[1].length;
		} // else
	} // while
	return retVal;
}
/*
*********************************************************************************************************************************
				End of Date Object additions
*********************************************************************************************************************************
*/
function fixTime(strTime){
	// allow for a hour only (2 pm) or 3pm)
	if (strTime.indexOf(':') == -1) {
		strTime = strTime + ' ';
		var intTemp = strTime.search(/\d\D/);
		strTime = strTime.substring(0,intTemp+1) + ':00 ' + strTime.substring(intTemp+1, 100);
	}

	strTime = strTime.replace(/\./,'').replace(/p\b/,'pm').replace(/a\b/,'am');
	return strTime;
}

function isValidTime() {
	var strTime = '';
	var boolAllowBlank = true;
	var intArgCount = (arguments.length > 2)? 2 : arguments.length;
	switch (intArgCount) {
		case 2:
			boolAllowBlank = arguments[1];

		case 1:
			strTime = arguments[0];
	}
	if (boolAllowBlank && !strTime.length)
		return true;

	strTime = fixTime(strTime);

	var td = new Date('01/01/2000 ' + strTime.replace(/\s\./ig,''));
	return (td!='NaN');
}

/*
=================================================================
 formatTime
	Parameters: strTime		: Time in a string format
	returns: string - formatted (H:NN am) version of the time.

=================================================================
*/
function formatTime(strTime) {
	if (strTime.search(/\S/)==-1)
		return strTime;

	strTime = fixTime(strTime);

	strTime = strTime.replace(/\s\./ig,'');
	var td = new Date('01/01/2000 ' + strTime);
	return td.getFDate('H:NN am');	
}

/*
=================================================================
 validateTimeField
	Parameters: fldObj		: Form Field Object containing the date
				bAllowBlank	: boolean, is a blank date valid?
	returns: boolean

=================================================================
*/
function validateTimeField(fldObj, bAllowBlank) {
	if (isValidTime(fldObj.value, bAllowBlank)) {
		fldObj.value = formatTime(fldObj.value);
		return true;
	}
	else {
		alert('The time entered is not a valid time format.\n(Valid formats include HH:MM, HH:MM am/pm, HH am/pm)');
		fldObj.focus();
		return false;
	}
}

function formatDate(strDate) {
	var td = new Date(strDate);
	return td.getFDate('MM/DD/YYYY');	
}

function isValidDate() {
	var strDate = '';
	var boolAllowBlank = true;
	var intArgCount = (arguments.length > 2)? 2 : arguments.length;
	switch (intArgCount) {
		case 2:
			boolAllowBlank = arguments[1];

		case 1:
			strDate = arguments[0];
	}
	if (boolAllowBlank && !strDate.length)
		return true;

	if ((strDate.replace(/[\d]/g,'')).length != 2)
		return false;
	strDate = strDate.replace(/\D/g, '/');
	
	var td = new Date(strDate);
	if (td=='NaN')
		return false;
	if (strDate.replace(/^0/, '').replace(/\/0/, '/') != td.getFDate('M/D/YYYY', '', 0))
		return false;
		
	return (td.getFDate('MM/DD/YYYY', '', 0).length == 10);
}

/*
=================================================================
 validateDateField
	Parameters: fldObj		: Form Field Object containing the date
				bAllowBlank	: boolean, is a blank date valid?
	returns: boolean

=================================================================
*/
function validateDateField(fldObj, bAllowBlank) {
	if (isValidDate(fldObj.value, bAllowBlank)) {
		fldObj.value = formatDate(fldObj.value);
		return true;
	}
	else {
		alert('The date entered is invalid or not MM/DD/YYYY format.');
		fldObj.focus();
		return false;
	}
}
