function isLeapYear(year) {
   if (year % 4 == 0) {
      if (year % 100 == 0) {
         return (year % 400 == 0);
      } else {
         return (true);
      }
   }
   return (false);
}

function daysInMonth(month, year) {
   switch (month) {
      case  0: return 31;  // january
      case  1:             // february
         if (isLeapYear(year)) {
            return 29;
         } else {
            return 28;
         }
      case  2: return 31;  // march
      case  3: return 30;  // april
      case  4: return 31;  // may
      case  5: return 30;  // june
      case  6: return 31;  // july
      case  7: return 31;  // august
      case  8: return 30;  // september
      case  9: return 31;  // october
      case 10: return 30;  // november
      case 11: return 31;  // december
   }
}

function DateAdd(datepart, number, date) {
   var d = new Date(date);
   switch (datepart) {
      // millisecond
      case "ms":
         return new Date(Date.parse(d) + (number));

      // second
      case "s":
      case "ss":
         return new Date(Date.parse(d) + (number*1000));

      // minute
      case "n":
      case "mi":
         return new Date(Date.parse(d) + (number*1000*60));

      // hour
      case "hh":
         return new Date(Date.parse(d) + (number*1000*60*60));

      // day
      case "d":
      case "dd":
         return new Date(Date.parse(d) + (number*1000*60*60*24));

      // week
      case "wk":
      case "ww":
         return new Date(Date.parse(d) + (number*1000*60*60*24*7));

      // month
      case "m":
      case "mm":
         var i = 0;
         var maxcurr = daysInMonth(d.getMonth(), d.getFullYear());
         var mm = (d.getMonth() + number) % 12;
         if (mm < 0) mm += 12;
         var yy = d.getFullYear() + Math.floor((number + d.getMonth()) / 12);
         var maxnext = daysInMonth(mm, yy);
         if (maxnext < d.getDate()) {
            i = (maxnext - d.getDate());
         }
         if (d.getDate() == maxcurr) {
            i = (maxnext - maxcurr);
         }
         return new Date(
            d.getFullYear(),
            d.getMonth()+number,
            d.getDate()+i,
            d.getHours(),
            d.getMinutes(),
            d.getSeconds());

      // quarter
      case "q":
      case "qq":
         var i = 0;
         var maxcurr = daysInMonth(d.getMonth(), d.getFullYear());
         var mm = (d.getMonth() + number*3) % 12;
         if (mm < 0) mm += 12;
         var yy = d.getFullYear() + Math.floor((number*3 + d.getMonth()) / 12);
         var maxnext = daysInMonth(mm, yy);
         if (maxnext < d.getDate()) {
            i = (maxnext - d.getDate());
         }
         if (d.getDate() == maxcurr) {
            i = (maxnext - maxcurr);
         }
         return new Date(
            d.getFullYear(),
            d.getMonth()+number*3,
            d.getDate()+i,
            d.getHours(),
            d.getMinutes(),
            d.getSeconds());

      // year
      case "yy":
      case "yyyy":
         var i = 0;
         if (d.getMonth() == 1) {
            if (d.getDate() == 29) {
               if (!isLeapYear(d.getFullYear() + number)) {
                  i = -1;
               }
            }
            if (d.getDate() == 28) {
               if (!isLeapYear(d.getFullYear())) {
                  if (isLeapYear(d.getFullYear() + number)) {
                     i = 1;
                  }
               }
            }
         }
         return new Date(
            d.getFullYear()+number,
            d.getMonth(),
            d.getDate()+i,
            d.getHours(),
            d.getMinutes(),
            d.getSeconds());
   }
}

var MONTH_NAMES=new Array('January','February','March','April','May','June','July','August','September','October','November','December','Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec');
var DAY_NAMES=new Array('Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday','Sun','Mon','Tue','Wed','Thu','Fri','Sat');
function LZ(x) {return(x<0||x>9?"":"0")+x}

// ------------------------------------------------------------------
// formatDate (date_object, format)
// Returns a date in the output format specified.
// The format string uses the same abbreviations as in getDateFromFormat()
// ------------------------------------------------------------------
	function formatDate(date,format) {
	format=format+"";
	var result="";
	var i_format=0;
	var c="";
	var token="";
	var y=date.getYear()+"";
	var M=date.getMonth()+1;
	var d=date.getDate();
	var E=date.getDay();
	var H=date.getHours();
	var m=date.getMinutes();
	var s=date.getSeconds();
	var yyyy,yy,MMM,MM,dd,hh,h,mm,ss,ampm,HH,H,KK,K,kk,k;
	// Convert real date parts into formatted versions
	var value=new Object();
	if (y.length < 4) {y=""+(y-0+1900);}
	value["y"]=""+y;
	value["yyyy"]=y;
	value["yy"]=y.substring(2,4);
	value["M"]=M;
	value["MM"]=LZ(M);
	value["MMM"]=MONTH_NAMES[M-1];
	value["NNN"]=MONTH_NAMES[M+11];
	value["d"]=d;
	value["dd"]=LZ(d);
	value["E"]=DAY_NAMES[E+7];
	value["EE"]=DAY_NAMES[E];
	value["H"]=H;
	value["HH"]=LZ(H);
	if (H==0){value["h"]=12;}
	else if (H>12){value["h"]=H-12;}
	else {value["h"]=H;}
	value["hh"]=LZ(value["h"]);
	if (H>11){value["K"]=H-12;} else {value["K"]=H;}
	value["k"]=H+1;
	value["KK"]=LZ(value["K"]);
	value["kk"]=LZ(value["k"]);
	if (H > 11) { value["a"]="PM"; }
	else { value["a"]="AM"; }
	value["m"]=m;
	value["mm"]=LZ(m);
	value["s"]=s;
	value["ss"]=LZ(s);
	while (i_format < format.length) {
		c=format.charAt(i_format);
		token="";
		while ((format.charAt(i_format)==c) && (i_format < format.length)) {
			token += format.charAt(i_format++);
			}
		if (value[token] != null) { result=result + value[token]; }
		else { result=result + token; }
		}
	return result;
	}
