/*  
 * DateFormatter.js - Javascript Simple Date Formatter
 * (C) 2004  Lasse Reichstein Nielsen
 * This file may be freely used as long as it is unmodified, and at your own risk. */

function DateFormatter(format, locale_opt) {
  this.formatString = format;
  this.locale = locale_opt || DateFormatter.DEFAULT_LOCALE;
}

DateFormatter.DEFAULT_LOCALE = { // English locale
  month:["January","February","March","April","May","June","July","August",
         "September","October","November","December"],
  shortMonth:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep",
	      "Oct","Nov","Dec"],
  day: ["Sunday","Monday","Tuesday","Wedensday",
	"Thursday","Friday","Saturday"],
  shortDay: ["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],
  AmPm: ["AM","PM"],
  usesAmPm: true,
  firstDayOfWeek: 0, // Sunday
  toOrdinal: function(number) {
    var n = Number(number); // ensure number
    var offset = ((((n%100)-(n%10))!=10) && (n%10)<4) ? n%10 : 0;
    var suffix = ["th","st","nd","rd"][offset];
    return number + suffix;
  }
};

DateFormatter.prototype.setLocale = function (locale) {
  this.locale = locale;
};

DateFormatter.prototype.format = function format(date) {
  var re = /([^a-zA-Z\\]*)((([a-zA-Z])\4*)(\.?)|\\([a-zA-Z]*\b|\\|\.))/g,
      resultStr = "", 
      locale = this.locale,
      lastIndex = 0,
      match;
  while((match = re.exec(this.formatString))) { 
    resultStr += match[1];
    var pattern = match[2];
    var patternChar = match[4];
    var patternLength = match[3] ? match[3].length : 0;
    var ordinal = (match[5] == ".");

    switch (patternChar) {
      case undefined: // string is "\word", "\." or "\\"
        resultStr += pattern.substring(1); // skip backslash
        break;
      case "y": // year
        if (patternLength == 2) {
          resultStr += this.formatNumber(date.getFullYear()%100,
					 2,
					 "0",
					 ordinal);
        } else {
          resultStr += this.formatNumber(date.getFullYear(),
                                         patternLength,
                                         "0",
                                         ordinal);
        }
        break;
      case "M": // month
        if (patternLength<=2) {
          resultStr += this.formatNumber(date.getMonth()+1,
                                         patternLength,
                                         "0",
                                         ordinal);
        } else if (patternLength == 3) {
          resultStr += this.locale.shortMonth[date.getMonth()];
        } else {
          resultStr += this.locale.month[date.getMonth()];
        }
        break;
      case "d": // day of month
        resultStr += this.formatNumber(date.getDate(),
				       patternLength,
				       "0",
				       ordinal);
        break;
      case "D": // day of week
        if (patternLength <= 2) {
          resultStr += this.formatNumber((date.getDay()-locale.firstDayOfWeek + 7)%7+1,
					 patternLength, 
					 "0", 
					 ordinal);
        } else if (patternLength == 3) {
          resultStr += locale.shortDay[date.getDay()];
        } else { 
          resultStr += locale.day[date.getDay()];
        }
        break;
      case "h": // 12 hours AM/PM 
        if (locale.usesAmPm) {
          var hour = date.getHours();
          resultStr += this.formatNumber((hour < 12 ? hour : hour - 12) || 12, 
					 patternLength, 
					 "0");
          break;
        } // else fallthrough
      case "H": // 24 hours 
        resultStr += this.formatNumber(date.getHours(), 
				       patternLength, 
				       "0", 
				       ordinal);
        break;
      case "m": // minutes
        resultStr += this.formatNumber(date.getMinutes(), 
				       patternLength, 
				       "0", 
				       ordinal);
        break;
      case "s": // seconds
        resultStr += this.formatNumber(date.getSeconds(), 
				       patternLength, 
				       "0", 
				       ordinal);
        break;
      case "A": // am/pm if appropriate
        if (this.locale.usesAmPm) {
	  var timeNum = (date.getHours()*100 +
			 date.getMinutes())*100+date.getSeconds();
	  resultStr += this.locale.AmPm[(timeNum>0 && timeNum <= 120000)?0:1];
	}
        break;
      default:
        resultStr += pattern;  
    }
    lastIndex = re.lastIndex;
  }
  resultStr += this.formatString.substring(lastIndex);
  return resultStr;
}

// --- private auxiliary functions, not for external use

DateFormatter.prototype.formatNumber = 
  function formatNumber(number, digits, padChar, ordinal) {
    var numStr = String(number);
    while(numStr.length < digits) {
      numStr = padChar + numStr;
    }
    return ordinal?this.locale.toOrdinal(numStr):numStr;
  };


