//function from http://forums.devshed.com/t39065/s84ded709f924610aa44fff827511aba3.html
//author appears to be Robert Pollard

function sprintf()
{
if (!arguments || arguments.length < 1 || !RegExp)
{
   return;
}
var str = arguments[0];
var re = /([^%]*)%('.|0|\x20)?(-)?(\d+)?(\.\d+)?(%|b|c|d|u|f|o|s|x|X)(.*)/;
var a = b = [], numSubstitutions = 0, numMatches = 0;
while (a = re.exec(str))
{
   var leftpart = a[1], pPad = a[2], pJustify = a[3], pMinLength = a[4];
   var pPrecision = a[5], pType = a[6], rightPart = a[7];

   numMatches++;
   if (pType == '%')
   {
      subst = '%';
   }
   else
   {
      numSubstitutions++;
      if (numSubstitutions >= arguments.length)
      {
         alert('Error! Not enough function arguments (' + (arguments.length - 1)
            + ', excluding the string)\n'
            + 'for the number of substitution parameters in string ('
            + numSubstitutions + ' so far).');
      }
      var param = arguments[numSubstitutions];
      var pad = '';
             if (pPad && pPad.substr(0,1) == "'") pad = leftpart.substr(1,1);
        else if (pPad) pad = pPad;
      var justifyRight = true;
             if (pJustify && pJustify === "-") justifyRight = false;
      var minLength = -1;
             if (pMinLength) minLength = parseInt(pMinLength);
      var precision = -1;
             if (pPrecision && pType == 'f')
                precision = parseInt(pPrecision.substring(1));
      var subst = param;
      switch (pType)
      {
      case 'b':
         subst = parseInt(param).toString(2);
         break;
      case 'c':
         subst = String.fromCharCode(parseInt(param));
         break;
      case 'd':
         subst = parseInt(param) ? parseInt(param) : 0;
         break;
      case 'u':
         subst = Math.abs(param);
         break;
      case 'f':
         subst = (precision > -1)
          ? Math.round(parseFloat(param) * Math.pow(10, precision))
           / Math.pow(10, precision)
          : parseFloat(param);
         break;
      case 'o':
         subst = parseInt(param).toString(8);
         break;
      case 's':
         subst = param;
         break;
      case 'x':
         subst = ('' + parseInt(param).toString(16)).toLowerCase();
         break;
      case 'X':
         subst = ('' + parseInt(param).toString(16)).toUpperCase();
         break;
      }
      var padLeft = minLength - subst.toString().length;
      if (padLeft > 0)
      {
         var arrTmp = new Array(padLeft+1);
         var padding = arrTmp.join(pad?pad:" ");
      }
      else
      {
         var padding = "";
      }
   }
   str = leftpart + padding + subst + rightPart;
}
return str;
}

Date.prototype.clone = function()
{
	retVal = new Date();
	retVal.setTime(this.getTime());
	return retVal;
};

Date.prototype.compare = function(op)
{
	if (this < op) return -1;
	if (this > op) return 1;
	return 0;
};

Date.prototype.sub = function(date)
{
	return (this.getTime()-date.getTime());
};

Date.prototype.add = function(milisecToAdd)
{
	var retVal = new Date();
	retVal.setTime(this.getTime()+milisecToAdd);
	return retVal;
};

Date.prototype.addComponents = function(day,hour,min,sec)
{
	var retVal = new Date();
	if (day === undefined) day = 0;
	if (hour === undefined) hour = 0;
	if (min === undefined) min = 0;
	if (sec === undefined) sec = 0;
	var originalOffset = this.getTimezoneOffset();
	retVal.setTime(this.getTime()+day*86400000+hour*3600000+min*60000+sec*1000);
	retVal.setTime(retVal.getTime()+(retVal.getTimezoneOffset()-originalOffset)*60000);
	return retVal;
};

Date.prototype.floorToDay = function(day)
{
	day = (((day-1)%7)+1);
	var curDay = this.getDay();if (curDay === 0) curDay = 7;
	return (curDay == day?this.clone():this.addComponents((day-curDay)>0?(day-curDay-7):(day-curDay), 0, 0, 0));
};

Date.prototype.ceilToDay = function(day)
{
	day = (((day-1)%7)+1);
	var curDay = this.getDay();if (curDay === 0) curDay = 7;
	return (curDay == day?this.clone():this.addComponents((day-curDay)<0?(day-curDay+7):(day-curDay), 0, 0, 0));
};

Date.prototype.roundInWeekToDay = function(day)
{
	day = (((day-1)%7)+1);
	var curDay = this.getDay();if (curDay === 0) curDay = 7;
	return (curDay == day?this.clone():this.addComponents(day-curDay, 0, 0, 0));
};

Date.prototype.getFirstDayOfMonth = function()
{
	var retVal = this.clone();
	retVal.setDate(1);
	return retVal;
};

Date.prototype.getLastDayOfMonth = function()
{
	var retVal = this.clone();
	retVal.setDate(1);
	retVal.setTime(retVal.getTime()+2764800000);
	retVal.setDate(1);
	retVal.setTime(retVal.getTime()-86400000);
	return retVal;
};

Date.prototype.getWeek = function()
{
	var reference = this.clone();
	reference.setMonth(0);
	reference.setDate(1);
	reference.setHours(0,0,0,0);
	
	var refDay = reference.getDay();if (refDay === 0) refDay = 7;
	return Math.ceil((this.getTime()-reference.getTime()+(refDay)*86400000)/604800000);
};

Date.prototype.isSameDayAs = function(date)
{
	return (
			this.getFullYear() === date.getFullYear() &&
			this.getMonth() === date.getMonth() &&
			this.getDate() === date.getDate()
			);	
};

Date.prototype.getISOFormat = function()
{
	return sprintf(
		'%04d-%02d-%02d %02d:%02d:%02d',
		this.getFullYear(),
		this.getMonth()+1,
		this.getDate(),
		this.getHours(),
		this.getMinutes(),
		this.getSeconds()
		);	
};

Date.prototype.getISOFormatDate = function()
{
	return sprintf(
		'%04d-%02d-%02d',
		this.getFullYear(),
		this.getMonth()+1,
		this.getDate()
		);	
};

Date.prototype.toString = function()
{
	return (this.toLocaleString());
};

Date.convertStringToDate = function(dateString)
{
	var dateString = dateString.replace(/\D/g, " ");
	var dObj = dateString.split(" ");
	for (var v = 0; v < 7; ++v) if (typeof dObj[v] == 'undefined')
			dObj[v] = 0;
	if (dObj[1] == 0) ++dObj[1];
	var myDate = new Date(dObj[0], (dObj[1]-1), dObj[2], dObj[3], dObj[4], dObj[5], dObj[6]);
	return myDate;		
};

Date.minimumOfDates = function(/*Date*/ op1,/*Date*/ op2,nullMeansNegtiveInfinit/* = true*/)
{
	if (typeof nullMeansNegtiveInfinit == 'undefined')
		nullMeansNegtiveInfinit = 1;
	
	if (op1 == null || op2 == null)
		return nullMeansNegtiveInfinit?null:op1 == null?op2:op1;
	return (op1.compare(op2) > 0)?op2:op1;
};

Date.maximunOfDates = function(/*Date*/ op1,/*Date*/ op2,nullMeansPositiveInfinit/* = true*/)
{
	if (typeof nullMeansPositiveInfinit == 'undefined')
		nullMeansPositiveInfinit = 1;
	if (op1 == null || op2 == null)
		return nullMeansPositiveInfinit?null:op1 == null?op2:op1;
	return (op1.compare(op2) > 0)?op1:op2;
};


/*
var test = new Date();
test.setFullYear(2008, 1, 2);
alert(test.floorToLastDayOfMonth());
*/
