/* 
  strftime functions originally implemented by 'Why The Lucky Stiff'
  <http://whytheluckystiff.net/>, described at:

    http://redhanded.hobix.com/inspect/showingPerfectTime.html

  Modified to fit in a single, unobtrusive javascript class by Mike West
  <http://mikewest.org/>:

    http://mikewest.org/archive/son-of-perfecttime-the-validationator

  Modified to fit the needs of the Textpattern rvm_localtime plugin by
  Ruud van Melick <http://vanmelick.com>

  LICENSE: I'm not sure what the original license chosen for this code was.
           I'm assuming it's liberal enough, and this class is released
           under the same license, whatever that turns out to be.
*/ 
 
function handleEvent(obj, event, func) {
	try {
		obj.addEventListener(event, func, false);
	} catch (e) {
		if (typeof obj['on'+event] == "function") {
			var existing = obj['on'+event];
			obj['on'+event] = function () { existing(); func(); };
		} else {
			obj['on'+event] = func;
		}
	}
}   

function PerfectTime() {
	var self = this;

	self.format = '%Y-%m-%d %H:%M.%S %z';

	self.strftime_funks = {
		zeropad: function( n ){ return n>9 ? n : '0'+n; },
		a: function(t) { return ['Sun','Mon','Tue','Wed','Thu','Fri','Sat'][t.getDay()] },
		A: function(t) { return ['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'][t.getDay()] },
		b: function(t) { return ['Jan','Feb','Mar','Apr','May','Jun', 'Jul','Aug','Sep','Oct','Nov','Dec'][t.getMonth()] },
		B: function(t) { return ['January','February','March','April','May','June', 'July','August', 'September','October','November','December'][t.getMonth()] },
		c: function(t) { return t.toString() },
		d: function(t) { return this.zeropad(t.getDate()) },
		H: function(t) { return this.zeropad(t.getHours()) },
		I: function(t) { return this.zeropad((t.getHours() + 12) % 12) },
		m: function(t) { return this.zeropad(t.getMonth()+1) }, // month-1
		M: function(t) { return this.zeropad(t.getMinutes()) },
		p: function(t) { return this.H(t) < 12 ? 'AM' : 'PM'; },
		S: function(t) { return this.zeropad(t.getSeconds()) },
		w: function(t) { return t.getDay() }, // 0..6 == sun..sat
		y: function(t) { return this.zeropad(this.Y(t) % 100); },
		Y: function(t) { return t.getFullYear() },
		z: function(t) { 
		   	if (t.getTimezoneOffset() > 0) {
		   		return "-" + this.zeropad(t.getTimezoneOffset()/60) + "00";
		   	} else {
		   		return "+" + this.zeropad(Math.abs(t.getTimezoneOffset())/60) + "00";
		   	}
		   },
		'%': function(t) { return '%' }
	}

	self.strftime = function (theDate, format) {
		var fmt = (format.length) ? format : self.format;
		for (var s in self.strftime_funks) {
			if (s.length == 1) {
				fmt = fmt.replace('%' + s, self.strftime_funks[s](theDate));
			}
		}
		return fmt;
	}

	self.instantiate = function () {
		var spans = document.getElementsByTagName('span');
		for (i=0, numSpans=spans.length; i < numSpans; i++) {
			if (spans[i].className.match(/unixtime/)) {
				self.processSpan(spans[i]);
			}
		}
	}

	self.processSpan = function (theSpan) {
		var re = /unixtime-(\d+)/;
		var GMT = parseInt(theSpan.className.replace(re, "$1")) * 1000;
		var newDate = new Date(GMT);
		var re = /unixtime-(\d+)-(\w+)/;
		var format = theSpan.className.replace(re, "$2");
		theSpan.innerHTML = self.strftime(newDate, self.hex2bin(format));
	}

	self.hex2bin = function (str) {
		return str.replace(/[0-9A-F]{2}/gi, 
			function(t) {
				return String.fromCharCode(parseInt(t, 16));
			}
		);
	}

	handleEvent(window, 'load', self.instantiate);
}

var timeThing = new PerfectTime();

