// formatDate :
// a PHP date like function, for formatting date strings
// authored by Svend Tofte <www.svendtofte.com>
// the code is in the public domain
//
// see http://www.svendtofte.com/code/date_format/
// and http://www.php.net/date
//
// thanks to 
//  - Daniel Berlin <mail@daniel-berlin.de>,
//    major overhaul and improvements
//  - Matt Bannon,
//    correcting some stupid bugs in my days-in-the-months list!
//
Date.prototype.formatDate = function (input,time) {

    var daysLong =    ["Sunday", "Monday", "Tuesday", "Wednesday", 
                       "Thursday", "Friday", "Saturday"];
    var daysShort =   ["Sun", "Mon", "Tue", "Wed", 
                       "Thu", "Fri", "Sat"];
    var monthsShort = ["Jan", "Feb", "Mar", "Apr",
                       "May", "Jun", "Jul", "Aug", "Sep",
                       "Oct", "Nov", "Dec"];
    var monthsLong =  ["January", "February", "March", "April",
                       "May", "June", "July", "August", "September",
                       "October", "November", "December"];

    var switches = {  a : function () {
            // Lowercase Ante meridiem and Post meridiem
            return date.getHours() > 11? "pm" : "am";
        },

        A : function () {
            // Uppercase Ante meridiem and Post meridiem
            return (this.a().toUpperCase ());
        },

        B : function (){
            // Swatch internet time. code simply grabbed from ppk,
            // since I was feeling lazy:
            // http://www.xs4all.nl/~ppk/js/beat.html
            var off = (date.getTimezoneOffset() + 60)*60;
            var theSeconds = (date.getHours() * 3600) + 
                             (date.getMinutes() * 60) + 
                              date.getSeconds() + off;
            var beat = Math.floor(theSeconds/86.4);
            if (beat > 1000) beat -= 1000;
            if (beat < 0) beat += 1000;
            if ((String(beat)).length == 1) beat = "00"+beat;
            if ((String(beat)).length == 2) beat = "0"+beat;
            return beat;
        },

        c : function () {
             return (this.Y() + "-" + this.m() + "-" + this.d() + "T" + 
                    this.h() + ":" + this.i() + ":" + this.s() + this.P());
        },

        d : function () {
             var j = String(this.j());
            return (j.length == 1 ? "0"+j : j);
        },

        D : function () {
             return daysShort[date.getDay()];
        },

        F : function () {
             return monthsLong[date.getMonth()];
        },

        g : function () {
             return date.getHours() > 12? date.getHours()-12 : date.getHours();
        },

        G : function () {
             return date.getHours();
        },

        h : function () {
             var g = String(this.g());
            return (g.length == 1 ? "0"+g : g);
        },

        H : function () {
             var G = String(this.G());
            return (G.length == 1 ? "0"+G : G);
        },

        i : function () {
             var min = String (date.getMinutes ());
            return (min.length == 1 ? "0" + min : min);
        },

        I : function () {
             var noDST = new Date ("January 1 " + this.Y() + " 00:00:00");
            return (noDST.getTimezoneOffset () == 
                    date.getTimezoneOffset () ? 0 : 1);
        },

        j : function () {
             return date.getDate();
        },

        l : function () {
             return daysLong[date.getDay()];
        },

        L : function () {
             var Y = this.Y();
            if (         
                (Y % 4 == 0 && Y % 100 != 0) ||
                (Y % 4 == 0 && Y % 100 == 0 && Y % 400 == 0)
                ) {
                return 1;
            } else {
                return 0;
            }
        },

        m : function () {
             var n = String(this.n());
            return (n.length == 1 ? "0"+n : n);
        },

        M : function () {
             return monthsShort[date.getMonth()];
        },

        n : function () {
             return date.getMonth()+1;
        },
        
        N : function () {
             var w = this.w();
            return (w == 0 ? 7 : w);
        },

        O : function () {
             var os = Math.abs(date.getTimezoneOffset());
            var h = String(Math.floor(os/60));
            var m = String(os%60);
            h.length == 1? h = "0"+h:1;
            m.length == 1? m = "0"+m:1;
            return date.getTimezoneOffset() < 0 ? "+"+h+m : "-"+h+m;
        },

        P : function () {
             var O = this.O();
            return (O.substr(0, 3) + ":" + O.substr(3, 2));
        },      

        r : function () {
             var r; // result
             r = this.D() + ", " + this.d() + " " + this.M() + " " + this.Y() +
             " " + this.H() + ":" + this.i() + ":" + this.s() + " " + this.O();
            return r;
        },

        s : function () {
             var sec = String (date.getSeconds ());
            return (sec.length == 1 ? "0" + sec : sec);
        },        

        S : function () {
             switch (date.getDate ()) {
                case  1: return ("st"); 
                case  2: return ("nd"); 
                case  3: return ("rd");
                case 21: return ("st"); 
                case 22: return ("nd"); 
                case 23: return ("rd");
                case 31: return ("st");
                default: return ("th");
            }
        },

        t : function () {
             var daysinmonths = [null,31,28,31,30,31,30,31,31,30,31,30,31];
            if (this.L()==1 && this.n()==2) return 29; // ~leap day
            return daysinmonths[this.n()];
        },

        U : function () {
             return Math.round(date.getTime()/1000);
        },

        w : function () {
             return date.getDay();
        },

        W : function () {
             var DoW = this.N ();
            var DoY = this.z ();

             var daysToNY = 364 + this.L () - DoY;
            if (daysToNY <= 2 && DoW <= (3 - daysToNY)) {
                return 1;
            }

             if (DoY <= 2 && DoW >= 5) {
                return new Date (this.Y () - 1, 11, 31).formatDate ("W");
            }
            
            var nyDoW = new Date (this.Y (), 0, 1).getDay ();
            nyDoW = nyDoW != 0 ? nyDoW - 1 : 6;

            if (nyDoW <= 3) { // First day of the year is a Thursday or earlier
                return (1 + Math.floor ((DoY + nyDoW) / 7));
            } else {  // First day of the year is a Friday or later
                return (1 + Math.floor ((DoY - (7 - nyDoW)) / 7));
            }
        },

        y : function () {
             var y = String(this.Y());
            return y.substring(y.length-2,y.length);
        },        

        Y : function () {
             if (date.getFullYear) {
                var newDate = new Date("January 1 2001 00:00:00 +0000");
                var x = newDate .getFullYear();
                if (x == 2001) {              
                    // i trust the method now
                    return date.getFullYear();
                }
            }
             var x = date.getYear();
            var y = x % 100;
            y += (y < 38) ? 2000 : 1900;
            return y;
        },

        z : function () {
             var t = new Date("January 1 " + this.Y() + " 00:00:00");
            var diff = date.getTime() - t.getTime();
            return Math.floor(diff/1000/60/60/24);
        },

        Z : function () {
             return (date.getTimezoneOffset () * -60);
        }        

    }

    function getSwitch(str) {
        if (switches[str] != undefined) {
            return switches[str]();
        } else {
            return str;
        }
    }

    var date;
    if (time) {
        var date = new Date (time);
    } else {
        var date = this;
    }

    var formatString = input.split("");
    var i = 0;
    while (i < formatString.length) {
        if (formatString[i] == "\\") {
             formatString.splice(i,1);
        } else {
            formatString[i] = getSwitch(formatString[i]);
        }
        i++;
    }

    return formatString.join("");
}

Date.DATE_ATOM    = "Y-m-d\TH:i:sP";
Date.DATE_ISO8601 = "Y-m-d\TH:i:sO";
Date.DATE_RFC2822 = "D, d M Y H:i:s O";
Date.DATE_W3C     = "Y-m-d\TH:i:sP";