
Date.implement({
	
/********************************************************************
 * jpl New */
	getPreviousMonth: function() {
		var result = new Date(this);
		result.setDate(1);
		result.setMonth(result.getMonth()-1);
		return result;
	},
	
	getNextMonth: function() {
		var result = new Date(this);
		result.setDate(1);  // avoid bug when getMonth()+1 === +30days (problem Feb to March!)
		result.setMonth(result.getMonth()+1);
		return result;
	},
/*******************************************************************/


	format: function(f){
		if (!this.isValid()) return 'invalid date';
		f = f || '%x %X';
		
		var formats = {
			db: '%Y-%m-%d %H:%M:%S',
			compact: '%Y%m%dT%H%M%S',
			iso8601: '%Y-%m-%dT%H:%M:%S%T',
			rfc822: '%a, %d %b %Y %H:%M:%S %Z',
			'short': '%d %b %H:%M',
			'long': '%B %d, %Y %H:%M'
		};
		var pad = function(what, length, string){
			if (!string) string = '0';
			return new Array(length - String(what).length + 1).join(string) + what;
		};

		f = formats[f.toLowerCase()] || f; // replace short-hand with actual format
		var d = this;
		return f.replace(/%([a-z%])/gi,
			function($0, $1){
				switch ($1){
					case 'a': return Date.getMsg('days_abbr')[d.get('day')];
					case 'A': return Date.getMsg('days')[d.get('day')];
					case 'b': return Date.getMsg('months_abbr')[d.get('month')];
					case 'B': return Date.getMsg('months')[d.get('month')];
					case 'c': return d.format('%a %b %d %H:%m:%S %Y');
					case 'd': return d.get('date');							// jpl
					case 'D': return pad(d.get('date'), 2);					// jpl
					case 'e': return pad(d.get('date'), 2, ' ');
					case 'h': return d.get('hr');							// jpl
					case 'H': return pad(d.get('hr'), 2);
					case 'i': return ((d.get('hr') % 12) || 12);			// jpl
					case 'I': return pad((d.get('hr') % 12) || 12, 2);
					case 'j': return pad(d.get('dayofyear'), 3);
					case 'k': return pad(d.get('hr'), 2, ' ');
					case 'l': return pad((d.get('hr') % 12) || 12, 2, ' ');
					case 'L': return pad(d.get('ms'), 3);
					case 'm': return d.get('mo') + 1;						// jpl
					case 'M': return pad((d.get('mo') + 1), 2);				// jpl
					case 'N': return pad(d.get('min'), 2);					// jpl
					case 'M': return pad(d.get('min'), 2);
					case 'o': return d.get('ordinal');
					case 'p': return Date.getMsg(d.get('ampm'));
					case 'P': return Date.getMsg(d.get('ampm')).toUpperCase();	// jpl
					case 'Q': return (d.get('min') > 0 ? ':' + pad(d.get('min'), 2) : ''); // jpl
					case 'r': return d.get('hr') < 12 ? '' : 'p';				// jpl
					case 'R': return d.get('hr') < 12 ? '' : 'P';				// jpl
					case 's': return Math.round(d / 1000);
					case 'S': return pad(d.get('seconds'), 2);
					case 'U': return pad(d.get('week'), 2);
					case 'w': return d.get('day');
					case 'x': return d.format(Date.getMsg('shortDate'));
					case 'X': return d.format(Date.getMsg('shortTime'));
					case 'y': return d.get('year').toString().substr(2);
					case 'Y': return d.get('year');
					/*<1.2compat>*/case 'T': return d.get('GMTOffset');/*</1.2compat>*/
					case 'z': return d.get('GMTOffset');
					case 'Z': return d.get('Timezone');
				}
				return $1;
			}
		);
	},
	
	
	dateValue: function() {
		var result = new Date(this);
		result.set('hr', 0);
		result.set('min', 0);
		result.set('sec', 0);
		return result;
	}
});


$extend(Date, {
	
	//===============================================================
	// jpl handy additional static functions:
	isValidTime: function(theTime) {
		return theTime.match(/^ *(((0?[0-9]|1[0-9]|2[0-3])(:[0-5][0-9])?)|((0?[0-9]|1[0-2])(:[0-5][0-9])? *(a|p|A|P)(m|M))) *$/);
	},
	isValidDate: function(theDate) {
		return (theDate.length > 0  &&  Date.parse(theDate) > 0);
	},
	
	min: function(date1, date2) {
		return (date1 < date2 ? date1 : date2);
	},
	
	max: function(date1, date2) {
		return (date1 < date2 ? date2 : date1);
	},
	
	parseTime: function(theTime) {
		var fieldSet = theTime.split(':');
		var theHour = parseInt(fieldSet[0].replace(/[^\d]/, ''));
		if(theTime.test(/pm/i))
			theHour = (theHour + 12) % 24
			
		var theMinute
		if(fieldSet.length >=2)
			theMinute = parseInt(fieldSet[1].replace(/[^\d]/, ''));
		
		if(isNaN(theHour)  ||  theHour == undefined  || theMinute == undefined  ||  isNaN(theMinute))
			return false
		return {hour: theHour % 24, minute: theMinute % 60}
	}
	//===============================================================
});


function $D(theDate) {
	return Date.parse(theDate);
};


