/**
* Date handling functions.
* 
* common javascript pitfalls (about date handling): [copied 1:1 from Bs_DatePicker.class.js]
*   - parseInt('09') won't return what you'd think. numbers with a 0 in front are treated as 
*     octal in javascript. use parseInt('09', 10) to specify the base 10.
*   - mozilla (at least 1.2beta) returns 2 digits for pre2000 dates in Date.getYear(). 
*     example: 98 for 1998. for post2000 years it returns 3 strange digits. for 2003 it returns 
*     103 and for 2004 it returns 104. rick says that it returns the 'years since 1900', which 
*     makes sense. i think that's bullshit.
*     todo: check getFullYear() if that helps, but it is js1.3 :/
*   - the javascript Date object has the methods 
*       getYear() to fetch the year
*       getMonth() to fetch the month
*       and not getDay() but getDate() to fetch the day. how stupid.
*   - while the year 2003 means 2003 and the day 3 means the 3rd of the month, the month 2 
*     does not mean february in javascript. months start at 0 (january) and end at 11 (december). 
*     very confusing.
*   - in js the weekday 0 is sunday, not monday. monday is 1, tuesday is 2, ...
* 
* @package    javascript_core
* @subpackage date
* @copyright  blueshoes
*/



/**
* tells if this is a valid date.
* @access public
* @param  int year (4 digits)
* @param  int month (1-12 not 0-11!)
* @param  int day (1-31)
* @return bool
* @since  bs-4.6
*/
function bs_isValidDate(year, month, day) {
	//date validation
	if (year >= 1970) {
		//i can use the javascript date object to validate the date. lucky me.
		var tDate = new Date(year, month -1, day);
		if (day   != tDate.getDate())               return false;
		if (month != (tDate.getMonth() +1))         return false;
		if (year  != bs_fixYear(tDate.getYear())) return false;
	} else {
		//doing some manual checks
		if ((day   < 1)    || (day   > 31))   return false;
		if ((month < 1)    || (month > 12))   return false;
		if ((year  < 1000) || (year  > 3000)) return false;
	}
	//somehow even the js date object does not detect 2003-02-31 as wrong. so we do that 
	//manually here.
	if (day > 28) {
		if (bs_getNumberOfDays(year, month) < day) return false;
	}
	return true;
}


/**
* Takes a year returned from javascript, fixes it, and returns it.
* 
* Examples:  
*  - 98  => 1998   netscape/mozilla returns 2 digits for pre2000 dates
*  - 103 => 2003   netscape/mozilla returns 3 digits for post2000 dates
* 
* @access public
* @param  int year
* @return int (year)
* @todo   check getFullYear() if that helps, but it is js1.3 :/
*/
function bs_fixYear(year) {

	if (year < 1000) {
		year = parseInt(1900 + year, 10);
	} 
	
	return year;
}


/*
function bs_fixYear(year) {

	if (year < 100) {
		year = parseInt('19' + year, 10);
	} else if ((year >= 100) && (year < 110)) {
		year = parseInt(200 + '' + year.toString().substr(2, 1), 10);
	} 
	
	return year;
}
*/



/**
* Tells how many days the given month has.
* @access public
* @param  int year  (eg 2003)
* @param  int month (1=jan, 12=dec)
* @return int (28-31)
*/
function bs_getNumberOfDays(year, month) {
	switch (month) {
		case 2:
			if (bs_isLeapYear(year)) return 29;
			return 28;
			break;
		case 1:
		case 3:
		case 5:
		case 7:
		case 8:
		case 10:
		case 12:
			return 31;
			break;
		default:
			return 30;
	}
}


/**
* Takes any date and converts it to iso date.
* iso date: 
*   - yyyy-mm-dd (eg 2003-12-31)
* some date: 
*   - european: dd.mm.yyyy (eg 31.12.2003)
*   - american: mm/dd/yyyy (eg 12/31/2003)
*   - iso     : yyyy-mm-dd (eg 2003-12-31)
* short forms: 
*   - the day, month and year may be shortened, so 1.12.03 would be valid.
*     if the year is shortened then < 30 means 2000 and >= 30 means 1900.
*     29=>2029, 30=>1930, 31=>1931 ...
* if allowTime is not set to false then:
*   a date can have a time attached in the form of hh:mm:ss or hh:mm. 
*   example: '31.12.2003 23:59:59' 
*   it will then be returned the same way.
* 
* something like 31.2.2003 is not valid because the feb never has 31 days.
* 
* @access public
* @param  string someDate (see above)
* @param  bool allowTime (allow a time definition, see above, default is true)
* @return string (iso date, yyyy-mm-dd)
* @throws bool false (if not a valid date.)
*/
function bs_dateToIsoDate(someDate, allowTime) {
	if (typeof(allowTime) == 'undefined') allowTime = true;
	
	var someTime = '';
	
	//trim
  someDate = someDate.replace(/^\s*/, '');
 	someDate = someDate.replace(/\s*$/, '');
	
	//short returns
	if (someDate.length <  6) return false;
	if (someDate.length > 10) {
		if (allowTime) {
			var tmp = someDate.split(' ', 2);
			if (tmp.length == 2) {
				someDate = tmp[0];
				if ((tmp[1].length == 5) || (tmp[1].length == 8)) {
					someTime = tmp[1];
				}
			}
		} else {
			someDate = someDate.substr(0, 10);
			//return false;
		}
	}
	
	//split based on format
	if (someDate.indexOf('/') >= 0) {
		//  mm/dd/yyyy
		var chunks = someDate.split('/');
		if (chunks.length != 3) return false; //naaaah
		var day   = parseInt(chunks[1], 10);
		var month = parseInt(chunks[0], 10);
		var year  = parseInt(chunks[2], 10);
	} else if (someDate.indexOf('-') >= 0) {
		//  yyyy/mm/dd
		var chunks = someDate.split('-');
		if (chunks.length != 3) return false; //naaaah
		var day   = parseInt(chunks[2], 10);
		var month = parseInt(chunks[1], 10);
		var year  = parseInt(chunks[0], 10);
	} else if (someDate.indexOf('.') >= 0) {
		//  dd.mm.yyyy
		var chunks = someDate.split('.');
		if (chunks.length != 3) return false; //naaaah
		var day   = parseInt(chunks[0], 10);
		var month = parseInt(chunks[1], 10);
		var year  = parseInt(chunks[2], 10);
	} else {
		//nada. we don't like things like "15 12 2002" or "15122002". or can you tell what "020302" means?
		return false;
	}
	
	//fix short years
	if (year < 100) {
		if (year < 30) {
			year += 2000;
		} else {
			year += 1900;
		}
	}
	
	//validate:
	if (!bs_isValidDate(year, month, day)) return false;
	
	//return iso date
	var ret = '';
	ret += year + '-';
	if (month < 10) ret += '0';
	ret += month + '-';
	if (day < 10) ret += '0';
	ret += day;
	
	if (someTime != '') {
		ret += ' ' + someTime;
	}
	
	return ret;
}

/**
* Tells if the year specified is a leap year or not. 
* <b>NOTE:</b> on't use years pre-1582.
* @access public
* @param  int year
* @return bool TRUE if leapYear; FALSE otherwise
*/
function bs_isLeapYear(year) { 
	return (((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0));
}




