
// used by dateAdd, dateDiff, datePart
// note: less strict than VBScript's isDate, since JS allows invalid dates to overflow (e.g. Jan 32 transparently becomes Feb 1)
function isDate(p_Expression){
	return !isNaN(new Date(p_Expression));		// <<--- this needs checking
}

// REQUIRES: isDate()
function dateAdd(p_Interval, p_Number, p_Date){
	if(!isDate(p_Date)){return "invalid date: '" + p_Date + "'";}
	if(isNaN(p_Number)){return "invalid number: '" + p_Number + "'";}	

	p_Number = new Number(p_Number);
	var dt = new Date(p_Date);
	switch(p_Interval.toLowerCase()){		
		case "y":		// day of year
		case "d":		// day
		case "w": {		// weekday
			dt.setDate(dt.getDate() + p_Number);
			break;
		}		
		case "h": {		// hour
			dt.setHours(dt.getHours() + p_Number);
			break;
		}		
		default: {
			return "invalid interval: '" + p_Interval + "'";
		}
	}
	return dt;
}

function dateAdd2(p_Interval, p_Number, p_Date){
	if(!isDate(p_Date)){return "invalid date: '" + p_Date + "'";}
	if(isNaN(p_Number)){return "invalid number: '" + p_Number + "'";}	

	p_Number = parseInt(p_Number);
	var test = new Date(p_Date);
	dt = new Date(test.getTime() + p_Number*24*60*60*1000);
	
	return dt;
}

// REQUIRES: isDate()
// NOT SUPPORTED: firstdayofweek and firstweekofyear (defaults for both)
function dateDiff(p_Interval, p_Date1, p_Date2, p_firstdayofweek, p_firstweekofyear){
	if(!isDate(p_Date1)){return "invalid date: '" + p_Date1 + "'";}
	if(!isDate(p_Date2)){return "invalid date: '" + p_Date2 + "'";}
	var dt1 = new Date(p_Date1);
	var dt2 = new Date(p_Date2);
	
	var one_day=1000*60*60*24;
	
	var nDays  = Math.ceil((dt2.getTime()-dt1.getTime())/(one_day));
	return  nDays;	
}


// REQUIRES: isDate(), dateDiff()
// NOT SUPPORTED: firstdayofweek and firstweekofyear (does system default for both)
function datePart(p_Interval, p_Date, p_firstdayofweek, p_firstweekofyear){
	if(!isDate(p_Date)){return "invalid date: '" + p_Date + "'";}

	var dtPart = new Date(p_Date);
	switch(p_Interval.toLowerCase()){
		case "yyyy": return dtPart.getFullYear();
		case "q": return parseInt(dtPart.getMonth()/3)+1;
		case "m": return dtPart.getMonth()+1;
		case "y": return dateDiff("y", "1/1/" + dtPart.getFullYear(), dtPart);			// day of year
		case "d": return dtPart.getDate();
		case "w": return dtPart.getDay();	// weekday		
		case "h": return dtPart.getHours();		
		default: return "invalid interval: '" + p_Interval + "'";
	}
}


// ====================================
// bootstrap different capitalizations
function IsDate(p_Expression){ 	return isDate(p_Expression); }
function DateAdd(p_Interval, p_Number, p_Date){	return dateAdd(p_Interval, p_Number, p_Date); }
function DateDiff(p_interval, p_date1, p_date2, p_firstdayofweek, p_firstweekofyear){ return dateDiff(p_interval, p_date1, p_date2, p_firstdayofweek, p_firstweekofyear); }
function DatePart(p_Interval, p_Date, p_firstdayofweek, p_firstweekofyear){	return datePart(p_Interval, p_Date, p_firstdayofweek, p_firstweekofyear); }

