/**
 * jDate Plugin for jQuery
 * @author: Michael Gilley <michael@180bydesign.com>
 * @site: www.180bydesign.com
 * @version: 1.0
 * @date: April 1, 2010
 * @dependencies: jQuery 1.3+
 * 
 * DESCRIPTION
 * This is a simple jQuery plugin that is basically just a wrapper 
 * for Php.js's date() function (http://phpjs.org/functions/date:380). 
 * I'm indebted to the good people listed below for most of this 
 * great code.
 * 
 * USAGE
 * Provided are both a jQuery function that returns a formatted 
 * date string and a jQuery method that inserts the string into any
 * matched elements as text. For further instructions see php's 
 * documentation on the function at 
 * http://php.net/manual/en/function.date.php.
 * 
 * EXAMPLES
 * $.date('F j, Y \\a\\t g:i:sa');  =>  January 1, 1970 at 12:00am
 * $('.date').date('Y-m-d H:i:s');  => <div class="date">1970-01-01 12:00:00</div>
 */
(function($) {
	
	 $.date = function(format, timestamp) {
	    // http://kevin.vanzonneveld.net
	    // +   original by: Carlos R. L. Rodrigues (http://www.jsfromhell.com)
	    // +      parts by: Peter-Paul Koch (http://www.quirksmode.org/js/beat.html)
	    // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
	    // +   improved by: MeEtc (http://yass.meetcweb.com)
	    // +   improved by: Brad Touesnard
	    // +   improved by: Tim Wiel
	    // +   improved by: Bryan Elliott
	    // +   improved by: Brett Zamir (http://brett-zamir.me)
	    // +   improved by: David Randall
	    // +      input by: Brett Zamir (http://brett-zamir.me)
	    // +   bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
	    // +   improved by: Brett Zamir (http://brett-zamir.me)
	    // +   improved by: Brett Zamir (http://brett-zamir.me)
	    // +   improved by: Theriault
	    // +  derived from: gettimeofday
	    // +      input by: majak
	    // +   bugfixed by: majak
	    // +   bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
	    // +      input by: Alex
	    // +   bugfixed by: Brett Zamir (http://brett-zamir.me)
	    // +   improved by: Theriault
	    // +   improved by: Brett Zamir (http://brett-zamir.me)
	    // +   improved by: Theriault
	    // +   improved by: Thomas Beaucourt  (http://www.webapp.fr)
	    // +   improved by: JT
	    // +   improved by: Theriault
	    var that = this,
	        jsdate, f, formatChr = /\\?([a-z])/gi, formatChrCb,
	        // Keep this here (works, but for code commented-out
	        // below for file size reasons)
	        //, tal= [],
	        _pad = function (n, c) {
	            if ((n = n + "").length < c) {
	                return new Array((++c) - n.length).join("0") + n;
	            } else {
	                return n;
	            }
	        },
	        txt_words = ["Sun", "Mon", "Tues", "Wednes", "Thurs", "Fri", "Satur",
	        "January", "February", "March", "April", "May", "June", "July",
	        "August", "September", "October", "November", "December"],
	        txt_ordin = {
	            1: "st",
	            2: "nd",
	            3: "rd",
	            21: "st", 
	            22: "nd",
	            23: "rd",
	            31: "st"
	        };
	    formatChrCb = function (t, s) {
	        return f[t] ? f[t]() : s;
	    };
	    f = {
	    // Day
	        d: function () { // Day of month w/leading 0; 01..31
	            return _pad(f.j(), 2);
	        },
	        D: function () { // Shorthand day name; Mon...Sun
	            return f.l().slice(0, 3);
	        },
	        j: function () { // Day of month; 1..31
	            return jsdate.getDate();
	        },
	        l: function () { // Full day name; Monday...Sunday
	            return txt_words[f.w()] + 'day';
	        },
	        N: function () { // ISO-8601 day of week; 1[Mon]..7[Sun]
	            return f.w() || 7;
	        },
	        S: function () { // Ordinal suffix for day of month; st, nd, rd, th
	            return txt_ordin[f.j()] || 'th';
	        },
	        w: function () { // Day of week; 0[Sun]..6[Sat]
	            return jsdate.getDay();
	        },
	        z: function () { // Day of year; 0..365
	            var a = new Date(f.Y(), f.n() - 1, f.j()),
	                b = new Date(f.Y(), 0, 1);
	            return Math.round((a - b) / 864e5) + 1;
	        },

	    // Week
	        W: function () { // ISO-8601 week number
	            var a = new Date(f.Y(), f.n() - 1, f.j() - f.N() + 3),
	                b = new Date(a.getFullYear(), 0, 4);
	            return 1 + Math.round((a - b) / 864e5 / 7);
	        },

	    // Month
	        F: function () { // Full month name; January...December
	            return txt_words[6 + f.n()];
	        },
	        m: function () { // Month w/leading 0; 01...12
	            return _pad(f.n(), 2);
	        },
	        M: function () { // Shorthand month name; Jan...Dec
	            return f.F().slice(0, 3);
	        },
	        n: function () { // Month; 1...12
	            return jsdate.getMonth() + 1;
	        },
	        t: function () { // Days in month; 28...31
	            return (new Date(f.Y(), f.n(), 0)).getDate();
	        },

	    // Year
	        L: function () { // Is leap year?; 0 or 1
	            var y = f.Y(), a = y & 3, b = y % 4e2, c = y % 1e2;
	            return 0 + (!a && (c || !b));
	        },
	        o: function () { // ISO-8601 year
	            var n = f.n(), W = f.W(), Y = f.Y();
	            return Y + (n === 12 && W < 9 ? -1 : n === 1 && W > 9);
	        },
	        Y: function () { // Full year; e.g. 1980...2010
	            return jsdate.getFullYear();
	        },
	        y: function () { // Last two digits of year; 00...99
	            return (f.Y() + "").slice(-2);
	        },

	    // Time
	        a: function () { // am or pm
	            return jsdate.getHours() > 11 ? "pm" : "am";
	        },
	        A: function () { // AM or PM
	            return f.a().toUpperCase();
	        },
	        B: function () { // Swatch Internet time; 000..999
	            var H = jsdate.getUTCHours() * 36e2, // Hours
	                i = jsdate.getUTCMinutes() * 60, // Minutes
	                s = jsdate.getUTCSeconds(); // Seconds
	            return _pad(Math.floor((H + i + s + 36e2) / 86.4) % 1e3, 3);
	        },
	        g: function () { // 12-Hours; 1..12
	            return f.G() % 12 || 12;
	        },
	        G: function () { // 24-Hours; 0..23
	            return jsdate.getHours();
	        },
	        h: function () { // 12-Hours w/leading 0; 01..12
	            return _pad(f.g(), 2);
	        },
	        H: function () { // 24-Hours w/leading 0; 00..23
	            return _pad(f.G(), 2);
	        },
	        i: function () { // Minutes w/leading 0; 00..59
	            return _pad(jsdate.getMinutes(), 2);
	        },
	        s: function () { // Seconds w/leading 0; 00..59
	            return _pad(jsdate.getSeconds(), 2);
	        },
	        u: function () { // Microseconds; 000000-999000
	            return _pad(jsdate.getMilliseconds() * 1000, 6);
	        },

	    // Timezone
	        e: function () {
	            return 'UTC';
	        },
	        I: function () { // DST observed?; 0 or 1
	            // Compares Jan 1 minus Jan 1 UTC to Jul 1 minus Jul 1 UTC.
	            // If they are not equal, then DST is observed.
	            var a = new Date(f.Y(), 0), // Jan 1
	                c = Date.UTC(f.Y(), 0), // Jan 1 UTC
	                b = new Date(f.Y(), 6), // Jul 1
	                d = Date.UTC(f.Y(), 6); // Jul 1 UTC
	            return 0 + ((a - c) !== (b - d));
	        },
	        O: function () { // Difference to GMT in hour format; e.g. +0200
	            var a = jsdate.getTimezoneOffset();
	            return (a > 0 ? "-" : "+") + _pad(Math.abs(a / 60 * 100), 4);
	        },
	        P: function () { // Difference to GMT w/colon; e.g. +02:00
	            var O = f.O();
	            return (O.substr(0, 3) + ":" + O.substr(3, 2));
	        },
	        T: function () {
	            return 'UTC';
	        },
	        Z: function () { // Timezone offset in seconds (-43200...50400)
	            return -jsdate.getTimezoneOffset() * 60;
	        },

	    // Full Date/Time
	        c: function () { // ISO-8601 date.
	            return 'Y-m-d\\Th:i:sP'.replace(formatChr, formatChrCb);
	        },
	        r: function () { // RFC 2822
	            return 'D, d M Y H:i:s O'.replace(formatChr, formatChrCb);
	        },
	        U: function () { // Seconds since UNIX epoch
	            return Math.round(jsdate.getTime() / 1000);
	        }
	    };
	    this.date = function (format, timestamp) {
	        that = this;
	        jsdate = (
	            (typeof timestamp === 'undefined') ? new Date() : // Not provided
	            (timestamp instanceof Date) ? new Date(timestamp) : // JS Date()
	            new Date(timestamp * 1000) // UNIX timestamp (auto-convert to int)
	        );
	        return format.replace(formatChr, formatChrCb);
	    };
	    return this.date(format, timestamp);
	};
	
	/**
	 * Plugin to inject date into objects
	 */
	$.fn.date = function(format, timestamp) {
			return this.text($.date(format, timestamp));
	};
	
})(jQuery);
