Date.prototype.getWeekNumber = function() {
	var d = new Date(this.getFullYear(), this.getMonth(), this.getDate(), 0, 0, 0);
	var DoW = d.getDay();
	d.setDate(d.getDate() - (DoW + 6) % 7 + 3); // Nearest Thu
	var ms = d.valueOf(); // GMT
	d.setMonth(0);
	d.setDate(4); // Thu in Week 1
	return Math.round((ms - d.valueOf()) / (7 * 864e5)) + 1;
};
Date.prototype.getDayOfYear = function() {
	var now = new Date(this.getFullYear(), this.getMonth(), this.getDate(), 0, 0, 0);
	var then = new Date(this.getFullYear(), 0, 0, 0, 0, 0);
	var time = now - then;
	return Math.floor(time / TimeUnit.DAYS);
};
var TimeUnit= {
	SECONDS : 1000, 
	MINUTES : 60000,
	HOURS : 3600000,
	DAYS : 86400000
};
function dateDiff(dateA, dateB, unit) {
	var sub = dateB.getTime() - dateA.getTime();
	sub = sub / unit;
	return Math.ceil(sub);
}

var DateFormat = Class.create({
	initialize : function(pattern, symbols) {
		if (pattern) {
			this.pattern = pattern;
		}
		if (symbols) {
			this.symbols = symbols;
		}
		},
	pattern : '%m/%d/%Y',
	symbols : { months : ['January','February','March','April','May','June','July','August','September','October','November','December'],
				sMonths: ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'],
				days : ['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'],
				sDays : ['Sun','Mon','Tue','Wed','Thu','Fri','Sat']
		},
	parseTwitter : function(str) {
		// date ex "Tue Apr 07 22:52:51 +0000 2009"
		var y = parseInt(str.substr(26,4));
		var m = this.parseMonth(str.substr(4,3), '%b');
		var d = parseInt(str.substr(8,2));
		var hr = parseInt(str.substr(11,2));
		var min = parseInt(str.substr(14,2));
		var sec = parseInt(str.substr(17,2));
		return new Date(y, m, d, hr, min, sec);
	},
	parseMonth : function(str, fmt) {
		var months = (fmt = '%b' ? this.symbols.sMonths : this.symbols.months);
		str = str.toLowerCase();
		for (var m = 0; m < 12; m++) {
			if (str == months[m].toLowerCase()) {
				return m;
			}
		} 
		return -1;
	}, 
	format : function(date) {
		var m = date.getMonth(), d = date.getDate(),  y = date.getFullYear(),  wn = date.getWeekNumber();
		var w = date.getDay();
		var s = {};
		var hr = date.getHours();
		var pm = (hr >= 12);
		var ir = (pm) ? (hr - 12) : hr;
		var dy = date.getDayOfYear();
		if (ir == 0)
			ir = 12;
		var min = date.getMinutes();
		var sec = date.getSeconds();
		s["%a"] = this.symbols.sDays[w]; // abbreviated weekday name [FIXME: I18N]
		s["%A"] = this.symbols.days[w]; // full weekday name
		s["%b"] = this.symbols.sMonths[m]; // abbreviated month name [FIXME: I18N]
		s["%B"] = this.symbols.months[m]; // full month name
		// FIXME: %c : preferred date and time representation for the current locale
		s["%C"] = 1 + Math.floor(y / 100); // the century number
		s["%d"] = (d < 10) ? ("0" + d) : d; // the day of the month (range 01 to 31)
		s["%e"] = d; // the day of the month (range 1 to 31)
		// FIXME: %D : american date style: %m/%d/%y
		// FIXME: %E, %F, %G, %g, %h (man strftime)
		s["%H"] = (hr < 10) ? ("0" + hr) : hr; // hour, range 00 to 23 (24h format)
		s["%I"] = (ir < 10) ? ("0" + ir) : ir; // hour, range 01 to 12 (12h format)
		s["%j"] = (dy < 100) ? ((dy < 10) ? ("00" + dy) : ("0" + dy)) : dy; // day of the year (range 001 to 366)
		s["%k"] = hr;		// hour, range 0 to 23 (24h format)
		s["%l"] = ir;		// hour, range 1 to 12 (12h format)
		s["%m"] = (m < 9) ? ("0" + (1+m)) : (1+m); // month, range 01 to 12
		s["%M"] = (min < 10) ? ("0" + min) : min; // minute, range 00 to 59
		s["%n"] = "\n";		// a newline character
		s["%p"] = pm ? "PM" : "AM";
		s["%P"] = pm ? "pm" : "am";
		// FIXME: %r : the time in am/pm notation %I:%M:%S %p
		// FIXME: %R : the time in 24-hour notation %H:%M
		s["%s"] = sec;
		s["%S"] = (sec < 10) ? ("0" + sec) : sec; // seconds, range 00 to 59
		s["%t"] = "\t";		// a tab character
		// FIXME: %T : the time in 24-hour notation (%H:%M:%S)
		s["%U"] = s["%W"] = s["%V"] = (wn < 10) ? ("0" + wn) : wn;
		s["%u"] = w + 1;	// the day of the week (range 1 to 7, 1 = MON)
		s["%w"] = w;		// the day of the week (range 0 to 6, 0 = SUN)
		// FIXME: %x : preferred date representation for the current locale without the time
		// FIXME: %X : preferred time representation for the current locale without the date
		s["%y"] = ('' + y).substr(2, 2); // year without the century (range 00 to 99)
		s["%Y"] = y;		// year with the century
		s["%%"] = "%";		// a literal '%' character
	
	var re = new RegExp("%.", "g");;
	var str = new String(this.pattern);
	return str.replace(re, function (par) { 
			return s[par] || par; 
		});
	}
});

