/* 

based on some code found at http://dren.ch/,
but modified so as not to munge the prototype
of the builtin Date object.

The original implementation was incomplete, but 
may be adequate.


*/

function _pad(num, n, p) {
  var s = '' + num;
  p = p || '0';
  while (s.length < n) {
    s = p + s;
  }
  return s;
}

var _MONTHS = [
  'January', 'February', 'March', 
  'April', 'May', 'June', 
  'July', 'August', 'September', 
  'October', 'November', 'December'
];
var _WEEKDAYS = [
  'Sunday', 'Monday', 'Tuesday', 'Wednesday',
  'Thursday', 'Friday', 'Saturday'
];
var _DAYS_PER_MONTH = [ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ];

var _fns = {
  A: function (d) { return _WEEKDAYS[d.getDay()] },
  a: function (d) { return _WEEKDAYS[d.getDay()].substring(0,3) },
  B: function (d) { return _MONTHS[d.getMonth()] },
  b: function (d) { return _MONTHS[d.getMonth()].substring(0,3) },
  C: function (d) { return Math.floor(d.getFullYear()/100); },
  c: function (d) { return d.toString() },
  D: function (d) { return _fns.m(d) + '/' +  _fns.d(d) + '/' + _fns.y(d); },
  d: function (d) { return _pad(d.getDate(),2,'0'); },
  e: function (d) { return _pad(d.getDate(), 2,' '); },
  F: function (d) { return _fns.Y(d) + '-' + _fns.m(d) + '-' + _fns.d(d); },
  H: function (d) { return _pad(d.getHours(), 2,'0'); },
  I: function (d) { return _pad((d.getHours() % 12 || 12), 2); },
  j: function (d) {
    var t = d.getDate();
    var m = d.getMonth() - 1;
    if (m > 1) {
      var y = d.getYear();
      if (((y % 100) == 0) && ((y % 400) == 0)) {
	++t;
      }
      else if ((y % 4) == 0) 
      {
	++t;
      }
    }
    while (m > -1) {
      t += _DAYS_PER_MONTH[m--];
    }
    return _pad(t, 3,'0');
  },
  k: function (d) { return _pad(d.getHours(), 2,' '); },
  l: function (d) { return _pad((d.getHours() % 12 || 12), 2,' ');},
  M: function (d) { return _pad(d.getMinutes(), 2,'0'); },
  m: function (d) { return _pad(d.getMonth()+1, 2,'0'); },
  n: function (d) { return "\n" },
  p: function (d) { return (d.getHours() > 11) ? 'PM' : 'AM' },
  P: function (d) { return (d.getHours() > 11) ? 'pm' : 'am' },
  R: function (d) { return _fns.H(d) + ':' + _fns.M(d) },
  r: function (d) { return _fns.I(d) + ':' + _fns.M(d) + ':' + _fns.S(d) + ' ' + _fns.p(d); },
  S: function (d) { return d.getSeconds().pad(2,'0') },
  s: function (d) { return Math.floor(d.getTime()/1000) },
  T: function (d) { return _fns.H(d) + ':' + _fns.M(d) + ':' + _fns.S(d); },
  t: function (d) { return "\t" },
  /*		U: function (d) { return false }, */
  u: function (d) { return(d.getDay() || 7) },
  /*		V: function (d) { return false }, */
  v: function (d) { return _fns.e(d) + '-' + _fns.b(d) + '-' + _fns.Y(d); },
  /*		W: function (d) { return false }, */
  w: function (d) { return d.getDay(); },
  X: function (d) { return d.toTimeString(); }, // wrong?
  x: function (d) { return d.toDateString(); }, // wrong?
  Y: function (d) { return d.getFullYear(); },
  y: function (d) { return _pad(d.getYear() % 100, 2); },
  // Z: function (d) { return d.toString().match(/\((.+)\)$/)[1]; },
  // z: function (d) { return d.getTimezoneOffset() }, // wrong
  // z: function (d) { return d.toString().match(/\sGMT([+-]\d+)/)[1]; },
  '%': function (d) { return '%'; }
};

_fns.h = _fns.b;

function strftime(dt, fmt) {
 var r = '';
  var n = 0;
  while(n < fmt.length) {
    var c = fmt.substring(n, n+1);
    if (c == '%') {
      c = fmt.substring(++n, n+1);
      r += (_fns[c]) ? _fns[c](dt) : c;
    } else {
      r += c;
    }
    ++n;
  }
  return r;
};
