/*
 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- 
 emDate v1.3 - (2004) by Lukas "Emka" Zeman (www.proteus.cz)
 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
 - feel free to use this code, but leave this header in it to help other users finding the actual version
 - find actual version at http://www.proteus.cz/tutorials/emdate/
 
 - big thanks to Martin "Cohen" (www.martincohen.info) for help with the first version of this script
*/



// Date.prototype.format
// - returns string with formatted date according to the given pattern (e.g. Y-m-d);
Date.prototype.format   = function(pattern) {
	var returnString = '';
	var regString    = pattern;
	var letters      = pattern.split('');

	for (var i = 0; i < letters.length; i++) {
		if (/[A-Za-z]/.test(letters[i]) && this.patterns[letters[i]]) {
			returnString += this.patterns[letters[i]].setVar(this);
		} else {
			returnString += letters[i];
		}
	}
	return returnString;
}

// Date.prototype.validate 
// - returns true, if the given date string match the given pattern
Date.prototype.validate = function(dateString, pattern) {
	var regString = '';
	var letters   = pattern.split('');
	var date      = new Array;

	// makes the reg. exp. for the whole dateString
	for (var i = 0; i < letters.length; i++) {
		if (/[A-Za-z]/.test(letters[i]) && this.patterns[letters[i]]) {
			if (typeof(this.patterns[letters[i]].reg) == 'function') {
				regString += this.patterns[letters[i]].reg();
			}
			else {
				regString += this.patterns[letters[i]].reg;
			}
		}
		else {
			regString  += '[' + letters[i] + ']';
		}
	}

	r1 = new RegExp('^'+regString+'$','g'); // the final RegExp
	if (!r1.test(dateString)) return false; // if the dateString doesn't match the reg. exp. return false

	// now we now that the string correspond to reg. exp. but we have to do other tests
	r2 = new RegExp('^'+regString+'$','g');
	var parsedArray = r2.exec(dateString);
	var date        = new Array;
	var letters     = pattern.split(new RegExp('[^a-zA-Z]+'));
	for (var i = 0; i < letters.length; i++) {
		if (this.patterns[letters[i]].getVar) {
			this.patterns[letters[i]].getVar(parsedArray[i + 1], date);
		}
	}

	// testing if given day exists in given month
	if (date['day'] && date['month']) {
		var maxDays = 31;
		if (date['month'] == 2) {
			if (date['year'] && (date['year']%4 == 0)) {
				maxDays = 29;
			} else {
				maxDays = 28;
			}
		}
		if ((date['month'] == 4) || (date['month'] == 6) || (date['month'] == 9) || (date['month'] == 11)) {maxDays = 30;}
		if (date['day'] > maxDays) {return false;}
	}
	
	var returnDate = new Date();

	if (typeof(date['year'])    != "undefined") {returnDate.setYear(date['year']);}
	if (typeof(date['minutes']) != "undefined") {returnDate.setMinutes(date['minutes']);}
	if (typeof(date['hours'])   != "undefined") {returnDate.setHours(date['hours']);}
	if (typeof(date['day'])     != "undefined") {returnDate.setDate(date['day']);}
	if (typeof(date['month'])   != "undefined") {returnDate.setMonth(date['month']-1);}
	
	// returns Date object, if successful
	return returnDate;
}

Date.prototype.getYearFixed = function() {
	var year = this.getYear();
	if (year < 1000) {
		if (year < 70) {year += 2000;} else {year += 1900;}
	}
	return year;
}

Date.prototype.roundMinutes = function(step) {
	var m = Math.round(this.getMinutes() / step) * step;
	this.setMinutes(m < 0 ? 0 : m);
}

Date.prototype.dayNames = [
	'Neděle', 'Pondělí', 'Úterý', 'Středa', 'Čtvrtek', 'Pátek', 'Sobota'
]

Date.prototype.dayNamesShort = [
	'Ne', 'Po', 'Út', 'St', 'Čt', 'Pá', 'So'
]

Date.prototype.monthNames = [
	'Leden', 'Únor', 'Březen', 'Duben', 'Květen', 'Červen', 'Červenec',
	'Srpen', 'Září', 'Říjen', 'Listopad', 'Prosinec'
]

// Date.prototype.patterns
// - defines all the patterns needed for validation and formatting
// - I've used the same patterns as in the PHP Date function (http://www.php.net/manual/en/function.date.php)
Date.prototype.patterns = new Array();

	 // j - Day of the month without leading zeros | 1 to 31
	Date.prototype.patterns['j'] = {
	 reg:    '([1-9]|[12][0-9]|3[01])', // regular expression for parsing
	 getVar: function(num, date) {      // where to put parsed string, needed for better validation
			date['day'] = num;
			return date;
	 },
	 setVar: function(date) {
			return date.getDate(); // returns formated string
		}
	}

	 // d - Day of the month, 2 digits with leading zeros | 01 to 31
	Date.prototype.patterns['d'] = {
		reg:    '(0[1-9]|[12][0-9]|3[01])',
		getVar: function(num, date) {
			date['day'] = num * 1; // strip leading zero, better then parseInt
			return date;
		},
		setVar: function(date) {
			return (date.getDate() < 10) ? ('0' + date.getDate()) : (date.getDate());
		}
	}

	 // n - Numeric representation of a month, without leading zeros | 1 through 12 
	Date.prototype.patterns['n'] = {
		reg:    '([1-9]|1[012])',
		getVar: function(num, date) {
			date['month'] = num;
			return date;
		},
		setVar: function(date) {
			return date.getMonth() + 1;
		}
	}

	 // m - Numeric representation of a month, with leading zeros | 01 through 12
	Date.prototype.patterns['m'] = {
		reg:    '(0[1-9]|1[012])',
		getVar: function(num, date) {
			date['month'] = num * 1;
			return date;
		},
		setVar: function(date) {
			var month = date.getMonth() + 1;
			month = (month < 10) ? ('0' + month) : (month);
			return month;
		}
	}

	 // F - A full textual representation of a month, such as January or March | January through December
	Date.prototype.patterns['F'] = {
		reg:    function() {
			var tmpDate   = new Date();
			var regString = '(';
			for (var i = 0; i < tmpDate.monthNames.length; i++) {
				regString += tmpDate.monthNames[i] + '|';
			}
			regString += ')';
			return regString;
		},
		getVar: function(monthName, date) {
			var tmpDate = new Date();
			for (var i = 0; i < tmpDate.monthNames; i++) {
				if (tmpDate.monthNames[i] == monthName) {
					return (i+1);
				}
			}
		},
		setVar: function(date) {
			return date.monthNames[date.getMonth()];
		}
	}

	 // Y - A full numeric representation of a year, 4 digits | Examples: 1999 or 2003
	Date.prototype.patterns['Y'] = {
		reg:    '([0-9]{4})',
		getVar: function(num, date) {
			date['year'] = num;
			return date;
		},
		setVar: function(date) {
			return date.getYearFixed();
		}
	}

	 // G - 24-hour format of an hour without leading zeros | 0 through 23
	Date.prototype.patterns['G'] = {
		reg:    '([0-9]|1[0-9]|2[0123])',
		getVar: function(num, date) {
			date['hours'] = num;
			return date;
		},
		setVar: function(date) {
			return date.getHours();
		}
	}

	 // H - 24-hour format of an hour with leading zeros | 00 through 23
	Date.prototype.patterns['H'] = {
		reg:    '([01][0-9]|2[0123])',
		getVar: function(num, date) {
			date['hours'] = num * 1;
			return date;
		},
		setVar: function(date) {
			return (date.getHours() < 10) ? ('0' + date.getHours()) : (date.getHours());
		}
	}

	 // i - Minutes with leading zeros | 00 to 59
	Date.prototype.patterns['i'] = {
		reg:    '([0-5][0-9])',
		getVar: function(num, date) {
			date['minutes'] = num * 1;
			return date;
		},
		setVar: function(date) {
			return (date.getMinutes() < 10) ? ('0' + date.getMinutes()) : (date.getMinutes());
		}
	}

	 // l - A full textual representation of the day of the week | Sunday through Saturday
	Date.prototype.patterns['l'] = {
		reg:    function() {
			var tmpDate   = new Date();
			var regS      = '(';
			for (var i = 0; i < tmpDate.dayNames.length; i++) {
				regS += tmpDate.dayNames[i] + '|';
			}
			regS += ')';
			return regS;
		},
		setVar: function(date) {
			return date.dayNames[date.getDay()];
		}
	}

	 // D - A textual representation of a day, three letters | Mon through Sun
	Date.prototype.patterns['D'] = {
		reg:    function() {
			var tmpDate   = new Date();
			var regS      = '(';
			for (var i = 0; i < tmpDate.dayNamesShort.length; i++) {
				regS += tmpDate.dayNames[i] + '|';
			}
			regS += ')';
			return regS;
		},
		setVar: function(date) {
			return date.dayNamesShort[date.getDay()];
		}
	}

	 // s - Seconds, with leading zeros | 00 to 59
	Date.prototype.patterns['s'] = {
		reg:    '([0-5][0-9])',
		getVar: function(num, date) {
			date['seconds'] = num * 1;
			return date;
		},
		setVar: function(date) {
			return (date.getSeconds() < 10) ? ('0' + date.getSeconds()) : (date.getSeconds());
		}
	}


	 // S - English ordinal suffix for the day of the month, 2 characters | st, nd, rd or th. Works well with j
	Date.prototype.patterns['S'] = {
		reg:    '(st|nd|rd|th)',
		setVar: function(date) {
			switch (date.getDate()) {
				case 1, 21, 31:
					return 'st';
				break;
				case 2, 22:
					return 'nd';
				break;
				case 3, 23:
					return 'rd';
				break;
				default:
					return 'th';
			}
	 }
	}