Date.prototype.format = function(str) {
    /*
        %A: Weekday (Monday - Sunday)
        %a: Weekday (Mon - Sun)
        %B: Month (January - December)
        %b: Month (Jan - Dec)
        %C: Year/100 (19 - 20)
        %c: Time and date (01/01/1900 12:00:00 AM - 12/31/2099 11:59:59 PM) [US format]
        %D: date (01/01/1900 - 12/31/2099)
        %d: Day (01 - 31)
        %e: Day ( 1 - 31)
        %F: Date (1900-01-01 - 2099-12-31)
        %G: ISO Year (1900 - 2099) [see http://en.wikipedia.org/wiki/ISO_8601#Week_dates]
        %g: ISO Year (00-99) [see http://en.wikipedia.org/wiki/ISO_8601#Week_dates]
        %H: Hour (00 - 23)
        %h: Month (Jan - Dec) [same as %b]
        %I: Hour (01 - 12)
        %j: Day of the year (001 - 366)
        %k: Hour ( 0-23)
        %l: Hour ( 1-12)
        %M: Minute (00 - 59)
        %m: Month (01 - 12)
        %n: Newline
        %p: AM/PM (AM - PM)
        %Q: Quarter (1 - 4)
        %R: Time (00:00 - 23:59)
        %r: Time (12:00:00 AM - 11:59:59 PM)
        %S: Second (00 - 59)
        %s: Number of seconds since the Epoch, UTC
        %T: Time (00:00:00 - 23:59:59)
        %t: Tab
        %U: Week (00 - 53) [Sunday as the first day of the week]
        %u: Weekday (1 - 7) [Monday as the first day of the week]
        %V: ISO Week (01 - 53) [see http://en.wikipedia.org/wiki/ISO_8601#Week_dates]
        %v: Date (1-Jan-1900 - 31-Dec-2099)
        %W: Week (00 - 53) [Monday as the first day of the week]
        %w: Weekday (1 - 7) [Sunday as the first day of the week]
        %X: Time (12:00:00 AM - 11:59:59 PM) [US format, same as %r]
        %x: Date (01/01/1900 - 12/31/2099) [US format, same as %D]
        %Y: Year (1900 - 2099)
        %y: Year (00 - 99)
        %Z: Time zone
        %z: Time zone offset (-1200 - +1200)
        %+: Date and Time (Mon Jan  1 00:00:00 GMT 1900 - Thu Dec 31 23:59:59 GMT 2099)
        %%: %
    */
    var month = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
    var day = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'];
    var ampm = ['AM', 'PM'];
    str = str.replace(/%%/g, '<%>');
    str = str.replace(/%c/g, '%x %X');
    str = str.replace(/%X/g, '%r');
    str = str.replace(/%x/g, '%D');
    str = str.replace(/%D/g, '%m/%d/%y');
    str = str.replace(/%F/g, '%Y-%m-%d');
    str = str.replace(/%h/g, '%b');
    str = str.replace(/%R/g, '%H:%M');
    str = str.replace(/%r/g, '%I:%M:%S %p');
    str = str.replace(/%T/g, '%H:%M:%S');    
    str = str.replace(/%w/g, '%e-%b-%Y');
    str = str.replace(/%\+/g, '%a %b %e %H:%M:%S %Z %Y')
    str = str.replace(/%A/g, day[(this.getDay() + 6) % 7]);
    str = str.replace(/%a/g, day[(this.getDay() + 6) % 7].toString().substr(0, 3));
    str = str.replace(/%B/g, month[this.getMonth()]);
    str = str.replace(/%b/g, month[this.getMonth()].toString().substr(0, 3));
    str = str.replace(/%C/g, this.getFullYear().toString().substr(0, 2));
    str = str.replace(/%d/g, this.getDate().toString().pad('0', 2, 'left'));
    str = str.replace(/%e/g, this.getDate().toString().pad(' ', 2, 'left'));
    str = str.replace(/%G/g, this.getISOYear());
    str = str.replace(/%g/g, this.getISOYear().toString().substr(-2));
    str = str.replace(/%H/g, this.getHours().toString().pad('0', 2, 'left'));
    str = str.replace(/%I/g, ((this.getHours() + 11) % 12 + 1).toString().pad('0', 2, 'left'));
    str = str.replace(/%j/g, this.getDayOfTheYear().toString().pad('0', 3, 'left'));
    str = str.replace(/%k/g, this.getHours().toString().pad(' ', 2, 'left'));
    str = str.replace(/%l/g, ((this.getHours() + 11) % 12 + 1).toString().pad(' ', 2, 'left'));
    str = str.replace(/%M/g, this.getMinutes().toString().pad('0', 2, 'left'));
    str = str.replace(/%m/g, (this.getMonth() + 1).toString().pad('0', 2, 'left'));
    str = str.replace(/%n/g, '\n');
    str = str.replace(/%Q/g, Math.floor(this.getMonth() / 4) + 1);
    str = str.replace(/%p/g, ampm[Math.floor(this.getHours() / 12)]);
    str = str.replace(/%S/g, this.getSeconds().toString().pad('0', 2, 'left'));
    str = str.replace(/%s/g, this.getTime() / 1000);
    str = str.replace(/%t/g, '\t');
    str = str.replace(/%U/g, Math.floor((this.getDayOfTheYear() + this.getFirstDayOfTheYear() - 1) / 7));
    str = str.replace(/%u/g, (this.getDay() + 6) % 7);
    str = str.replace(/%V/g, this.getISOWeek());
    str = str.replace(/%W/g, Math.floor((this.getDayOfTheYear() + (this.getFirstDayOfTheYear() + 6) % 7 - 1) / 7));
    str = str.replace(/%w/g, this.getDay());
    str = str.replace(/%Y/g, this.getFullYear());
    str = str.replace(/%y/g, this.getFullYear().toString().substr(-2));
    str = str.replace(/%Z/g, this.toString().substr(-4, 3));
    str = str.replace(/%z/g, this.getTimezoneOffsetString());
    str = str.replace(/<%>/g, '%');
    return str;
}

Date.prototype.getFirstDayOfTheYear = function() {
    /*
        Weekday of January 1 of the current year (0 - 6) [Sunday as the first day of the week]
    */
    var date = new Date();
    date.setFullYear(this.getFullYear())
    date.setMonth(0);
    date.setDate(1);
    return date.getDay();
}

Date.prototype.getDayOfTheYear = function() {
    /*
        Day of the year (1 - 366)
    */
    var days = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
    var year = this.getFullYear();
    var month = this.getMonth();
    var day = this.getDate();
    var dayOfTheYear = 0
    for (var i = 0; i < month; i++)
        dayOfTheYear += days[month];
    dayOfTheYear += day;
    if (month >= 2 && year % 4 == 0 && year % 400 != 0)
        dayOfTheYear++;
    return dayOfTheYear;
}

Date.prototype.getISOWeek = function() {
    /*
        ISO Week (1 - 53) [see http://en.wikipedia.org/wiki/ISO_8601#Week_dates]
    */
    var date = new Date();
    date.setTime(this.getTime() + (3 - (this.getDay() + 6) % 7) * 86400000);
    return Math.floor((date.getDayOfTheYear() + (date.getFirstDayOfTheYear() + 6) % 7 - 1) / 7) + 1;
}

Date.prototype.getISOYear = function() {
    /*
        ISO Year (1900 - 2099) [see http://en.wikipedia.org/wiki/ISO_8601#Week_dates]
    */
    var date = new Date();
    date.setTime(this.getTime() + (3 - (this.getDay() + 6) % 7) * 86400000);
    return date.getFullYear();
}

Date.prototype.getTimezoneOffsetString = function() {
    /*
        Time zone offset string (-1200 - +1200)
    */
    var offset = this.getTimezoneOffset();
    if (offset < 0)
        var sign = '+';
    else
        var sign = '-';
    var hour = Math.floor(Math.abs(offset) / 60).toString().pad('0', 2, 'left');
    var minute = (Math.abs(offset) % 60).toString().pad('0', 2, 'left');
    return sign + hour + minute;
}