Index: trunk/prototype/plugins/datejs/core-debug.js
===================================================================
--- trunk/prototype/plugins/datejs/core-debug.js	(revision 5341)
+++ trunk/prototype/plugins/datejs/core-debug.js	(revision 7143)
@@ -1,651 +1,865 @@
 /**
- * Version: 1.0 Alpha-1 
- * Build Date: 12-Nov-2007
- * Copyright (c) 2006-2007, Coolite Inc. (http://www.coolite.com/). All rights reserved.
- * License: Licensed under The MIT License. See license.txt and http://www.datejs.com/license/. 
- * Website: http://www.datejs.com/ or http://www.coolite.com/datejs/
+ * @version: 1.0 Alpha-1
+ * @author: Coolite Inc. http://www.coolite.com/
+ * @date: 2008-04-13
+ * @copyright: Copyright (c) 2006-2008, Coolite Inc. (http://www.coolite.com/). All rights reserved.
+ * @license: Licensed under The MIT License. See license.txt and http://www.datejs.com/license/. 
+ * @website: http://www.datejs.com/
  */
-
-/**
- * Gets the month number (0-11) if given a Culture Info specific string which is a valid monthName or abbreviatedMonthName.
- * @param {String}   The name of the month (eg. "February, "Feb", "october", "oct").
- * @return {Number}  The day number
- */
-Date.getMonthNumberFromName = function (name) {
-    var n = Date.CultureInfo.monthNames, m = Date.CultureInfo.abbreviatedMonthNames, s = name.toLowerCase();
-    for (var i = 0; i < n.length; i++) {
-        if (n[i].toLowerCase() == s || m[i].toLowerCase() == s) { 
-            return i; 
-        }
+ 
+(function () {
+    var $D = Date, 
+        $P = $D.prototype, 
+        $C = $D.CultureInfo,
+        p = function (s, l) {
+            if (!l) {
+                l = 2;
+            }
+            return ("000" + s).slice(l * -1);
+        };
+            
+    /**
+     * Resets the time of this Date object to 12:00 AM (00:00), which is the start of the day.
+     * @param {Boolean}  .clone() this date instance before clearing Time
+     * @return {Date}    this
+     */
+    $P.clearTime = function () {
+        this.setHours(0);
+        this.setMinutes(0);
+        this.setSeconds(0);
+        this.setMilliseconds(0);
+        return this;
+    };
+
+    /**
+     * Resets the time of this Date object to the current time ('now').
+     * @return {Date}    this
+     */
+    $P.setTimeToNow = function () {
+        var n = new Date();
+        this.setHours(n.getHours());
+        this.setMinutes(n.getMinutes());
+        this.setSeconds(n.getSeconds());
+        this.setMilliseconds(n.getMilliseconds());
+        return this;
+    };
+
+    /** 
+     * Gets a date that is set to the current date. The time is set to the start of the day (00:00 or 12:00 AM).
+     * @return {Date}    The current date.
+     */
+    $D.today = function () {
+        return new Date().clearTime();
+    };
+
+    /**
+     * Compares the first date to the second date and returns an number indication of their relative values.  
+     * @param {Date}     First Date object to compare [Required].
+     * @param {Date}     Second Date object to compare to [Required].
+     * @return {Number}  -1 = date1 is lessthan date2. 0 = values are equal. 1 = date1 is greaterthan date2.
+     */
+    $D.compare = function (date1, date2) {
+        if (isNaN(date1) || isNaN(date2)) { 
+            throw new Error(date1 + " - " + date2); 
+        } else if (date1 instanceof Date && date2 instanceof Date) {
+            return (date1 < date2) ? -1 : (date1 > date2) ? 1 : 0;
+        } else { 
+            throw new TypeError(date1 + " - " + date2); 
+        }
+    };
+    
+    /**
+     * Compares the first Date object to the second Date object and returns true if they are equal.  
+     * @param {Date}     First Date object to compare [Required]
+     * @param {Date}     Second Date object to compare to [Required]
+     * @return {Boolean} true if dates are equal. false if they are not equal.
+     */
+    $D.equals = function (date1, date2) { 
+        return (date1.compareTo(date2) === 0); 
+    };
+
+    /**
+     * Gets the day number (0-6) if given a CultureInfo specific string which is a valid dayName, abbreviatedDayName or shortestDayName (two char).
+     * @param {String}   The name of the day (eg. "Monday, "Mon", "tuesday", "tue", "We", "we").
+     * @return {Number}  The day number
+     */
+    $D.getDayNumberFromName = function (name) {
+        var n = $C.dayNames, m = $C.abbreviatedDayNames, o = $C.shortestDayNames, s = name.toLowerCase();
+        for (var i = 0; i < n.length; i++) { 
+            if (n[i].toLowerCase() == s || m[i].toLowerCase() == s || o[i].toLowerCase() == s) { 
+                return i; 
+            }
+        }
+        return -1;  
+    };
+    
+    /**
+     * Gets the month number (0-11) if given a Culture Info specific string which is a valid monthName or abbreviatedMonthName.
+     * @param {String}   The name of the month (eg. "February, "Feb", "october", "oct").
+     * @return {Number}  The day number
+     */
+    $D.getMonthNumberFromName = function (name) {
+        var n = $C.monthNames, m = $C.abbreviatedMonthNames, s = name.toLowerCase();
+        for (var i = 0; i < n.length; i++) {
+            if (n[i].toLowerCase() == s || m[i].toLowerCase() == s) { 
+                return i; 
+            }
+        }
+        return -1;
+    };
+
+    /**
+     * Determines if the current date instance is within a LeapYear.
+     * @param {Number}   The year.
+     * @return {Boolean} true if date is within a LeapYear, otherwise false.
+     */
+    $D.isLeapYear = function (year) { 
+        return ((year % 4 === 0 && year % 100 !== 0) || year % 400 === 0); 
+    };
+
+    /**
+     * Gets the number of days in the month, given a year and month value. Automatically corrects for LeapYear.
+     * @param {Number}   The year.
+     * @param {Number}   The month (0-11).
+     * @return {Number}  The number of days in the month.
+     */
+    $D.getDaysInMonth = function (year, month) {
+        return [31, ($D.isLeapYear(year) ? 29 : 28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month];
+    };
+ 
+    $D.getTimezoneAbbreviation = function (offset) {
+        var z = $C.timezones, p;
+        for (var i = 0; i < z.length; i++) {
+            if (z[i].offset === offset) {
+                return z[i].name;
+            }
+        }
+        return null;
+    };
+    
+    $D.getTimezoneOffset = function (name) {
+        var z = $C.timezones, p;
+        for (var i = 0; i < z.length; i++) {
+            if (z[i].name === name.toUpperCase()) {
+                return z[i].offset;
+            }
+        }
+        return null;
+    };
+
+    /**
+     * Returns a new Date object that is an exact date and time copy of the original instance.
+     * @return {Date}    A new Date instance
+     */
+    $P.clone = function () {
+        return new Date(this.getTime()); 
+    };
+
+    /**
+     * Compares this instance to a Date object and returns an number indication of their relative values.  
+     * @param {Date}     Date object to compare [Required]
+     * @return {Number}  -1 = this is lessthan date. 0 = values are equal. 1 = this is greaterthan date.
+     */
+    $P.compareTo = function (date) {
+        return Date.compare(this, date);
+    };
+
+    /**
+     * Compares this instance to another Date object and returns true if they are equal.  
+     * @param {Date}     Date object to compare. If no date to compare, new Date() [now] is used.
+     * @return {Boolean} true if dates are equal. false if they are not equal.
+     */
+    $P.equals = function (date) {
+        return Date.equals(this, date || new Date());
+    };
+
+    /**
+     * Determines if this instance is between a range of two dates or equal to either the start or end dates.
+     * @param {Date}     Start of range [Required]
+     * @param {Date}     End of range [Required]
+     * @return {Boolean} true is this is between or equal to the start and end dates, else false
+     */
+    $P.between = function (start, end) {
+        return this.getTime() >= start.getTime() && this.getTime() <= end.getTime();
+    };
+
+    /**
+     * Determines if this date occurs after the date to compare to.
+     * @param {Date}     Date object to compare. If no date to compare, new Date() ("now") is used.
+     * @return {Boolean} true if this date instance is greater than the date to compare to (or "now"), otherwise false.
+     */
+    $P.isAfter = function (date) {
+        return this.compareTo(date || new Date()) === 1;
+    };
+
+    /**
+     * Determines if this date occurs before the date to compare to.
+     * @param {Date}     Date object to compare. If no date to compare, new Date() ("now") is used.
+     * @return {Boolean} true if this date instance is less than the date to compare to (or "now").
+     */
+    $P.isBefore = function (date) {
+        return (this.compareTo(date || new Date()) === -1);
+    };
+
+    /**
+     * Determines if the current Date instance occurs today.
+     * @return {Boolean} true if this date instance is 'today', otherwise false.
+     */
+    
+    /**
+     * Determines if the current Date instance occurs on the same Date as the supplied 'date'. 
+     * If no 'date' to compare to is provided, the current Date instance is compared to 'today'. 
+     * @param {date}     Date object to compare. If no date to compare, the current Date ("now") is used.
+     * @return {Boolean} true if this Date instance occurs on the same Day as the supplied 'date'.
+     */
+    $P.isToday = $P.isSameDay = function (date) {
+        return this.clone().clearTime().equals((date || new Date()).clone().clearTime());
+    };
+    
+    /**
+     * Adds the specified number of milliseconds to this instance. 
+     * @param {Number}   The number of milliseconds to add. The number can be positive or negative [Required]
+     * @return {Date}    this
+     */
+    $P.addMilliseconds = function (value) {
+        this.setMilliseconds(this.getMilliseconds() + value * 1);
+        return this;
+    };
+
+    /**
+     * Adds the specified number of seconds to this instance. 
+     * @param {Number}   The number of seconds to add. The number can be positive or negative [Required]
+     * @return {Date}    this
+     */
+    $P.addSeconds = function (value) { 
+        return this.addMilliseconds(value * 1000); 
+    };
+
+    /**
+     * Adds the specified number of seconds to this instance. 
+     * @param {Number}   The number of seconds to add. The number can be positive or negative [Required]
+     * @return {Date}    this
+     */
+    $P.addMinutes = function (value) { 
+        return this.addMilliseconds(value * 60000); /* 60*1000 */
+    };
+
+    /**
+     * Adds the specified number of hours to this instance. 
+     * @param {Number}   The number of hours to add. The number can be positive or negative [Required]
+     * @return {Date}    this
+     */
+    $P.addHours = function (value) { 
+        return this.addMilliseconds(value * 3600000); /* 60*60*1000 */
+    };
+
+    /**
+     * Adds the specified number of days to this instance. 
+     * @param {Number}   The number of days to add. The number can be positive or negative [Required]
+     * @return {Date}    this
+     */
+    $P.addDays = function (value) {
+        this.setDate(this.getDate() + value * 1);
+        return this;
+    };
+
+    /**
+     * Adds the specified number of weeks to this instance. 
+     * @param {Number}   The number of weeks to add. The number can be positive or negative [Required]
+     * @return {Date}    this
+     */
+    $P.addWeeks = function (value) { 
+        return this.addDays(value * 7);
+    };
+
+    /**
+     * Adds the specified number of months to this instance. 
+     * @param {Number}   The number of months to add. The number can be positive or negative [Required]
+     * @return {Date}    this
+     */
+    $P.addMonths = function (value) {
+        var n = this.getDate();
+        this.setDate(1);
+        this.setMonth(this.getMonth() + value * 1);
+        this.setDate(Math.min(n, $D.getDaysInMonth(this.getFullYear(), this.getMonth())));
+        return this;
+    };
+
+    /**
+     * Adds the specified number of years to this instance. 
+     * @param {Number}   The number of years to add. The number can be positive or negative [Required]
+     * @return {Date}    this
+     */
+    $P.addYears = function (value) {
+        return this.addMonths(value * 12);
+    };
+
+    /**
+     * Adds (or subtracts) to the value of the years, months, weeks, days, hours, minutes, seconds, milliseconds of the date instance using given configuration object. Positive and Negative values allowed.
+     * Example
+    <pre><code>
+    Date.today().add( { days: 1, months: 1 } )
+     
+    new Date().add( { years: -1 } )
+    </code></pre> 
+     * @param {Object}   Configuration object containing attributes (months, days, etc.)
+     * @return {Date}    this
+     */
+    $P.add = function (config) {
+        if (typeof config == "number") {
+            this._orient = config;
+            return this;    
+        }
+        
+        var x = config;
+        
+        if (x.milliseconds) { 
+            this.addMilliseconds(x.milliseconds); 
+        }
+        if (x.seconds) { 
+            this.addSeconds(x.seconds); 
+        }
+        if (x.minutes) { 
+            this.addMinutes(x.minutes); 
+        }
+        if (x.hours) { 
+            this.addHours(x.hours); 
+        }
+        if (x.weeks) { 
+            this.addWeeks(x.weeks); 
+        }    
+        if (x.months) { 
+            this.addMonths(x.months); 
+        }
+        if (x.years) { 
+            this.addYears(x.years); 
+        }
+        if (x.days) {
+            this.addDays(x.days); 
+        }
+        return this;
+    };
+    
+    var $y, $m, $d;
+    
+    /**
+     * Get the week number. Week one (1) is the week which contains the first Thursday of the year. Monday is considered the first day of the week.
+     * This algorithm is a JavaScript port of the work presented by Claus Tøndering at http://www.tondering.dk/claus/cal/node8.html#SECTION00880000000000000000
+     * .getWeek() Algorithm Copyright (c) 2008 Claus Tondering.
+     * The .getWeek() function does NOT convert the date to UTC. The local datetime is used. Please use .getISOWeek() to get the week of the UTC converted date.
+     * @return {Number}  1 to 53
+     */
+    $P.getWeek = function () {
+        var a, b, c, d, e, f, g, n, s, w;
+        
+        $y = (!$y) ? this.getFullYear() : $y;
+        $m = (!$m) ? this.getMonth() + 1 : $m;
+        $d = (!$d) ? this.getDate() : $d;
+
+        if ($m <= 2) {
+            a = $y - 1;
+            b = (a / 4 | 0) - (a / 100 | 0) + (a / 400 | 0);
+            c = ((a - 1) / 4 | 0) - ((a - 1) / 100 | 0) + ((a - 1) / 400 | 0);
+            s = b - c;
+            e = 0;
+            f = $d - 1 + (31 * ($m - 1));
+        } else {
+            a = $y;
+            b = (a / 4 | 0) - (a / 100 | 0) + (a / 400 | 0);
+            c = ((a - 1) / 4 | 0) - ((a - 1) / 100 | 0) + ((a - 1) / 400 | 0);
+            s = b - c;
+            e = s + 1;
+            f = $d + ((153 * ($m - 3) + 2) / 5) + 58 + s;
+        }
+        
+        g = (a + b) % 7;
+        d = (f + g - e) % 7;
+        n = (f + 3 - d) | 0;
+
+        if (n < 0) {
+            w = 53 - ((g - s) / 5 | 0);
+        } else if (n > 364 + s) {
+            w = 1;
+        } else {
+            w = (n / 7 | 0) + 1;
+        }
+        
+        $y = $m = $d = null;
+        
+        return w;
+    };
+    
+    /**
+     * Get the ISO 8601 week number. Week one ("01") is the week which contains the first Thursday of the year. Monday is considered the first day of the week.
+     * The .getISOWeek() function does convert the date to it's UTC value. Please use .getWeek() to get the week of the local date.
+     * @return {String}  "01" to "53"
+     */
+    $P.getISOWeek = function () {
+        $y = this.getUTCFullYear();
+        $m = this.getUTCMonth() + 1;
+        $d = this.getUTCDate();
+        return p(this.getWeek());
+    };
+
+    /**
+     * Moves the date to Monday of the week set. Week one (1) is the week which contains the first Thursday of the year.
+     * @param {Number}   A Number (1 to 53) that represents the week of the year.
+     * @return {Date}    this
+     */    
+    $P.setWeek = function (n) {
+        return this.moveToDayOfWeek(1).addWeeks(n - this.getWeek());
+    };
+
+    // private
+    var validate = function (n, min, max, name) {
+        if (typeof n == "undefined") {
+            return false;
+        } else if (typeof n != "number") {
+            throw new TypeError(n + " is not a Number."); 
+        } else if (n < min || n > max) {
+            throw new RangeError(n + " is not a valid value for " + name + "."); 
+        }
+        return true;
+    };
+
+    /**
+     * Validates the number is within an acceptable range for milliseconds [0-999].
+     * @param {Number}   The number to check if within range.
+     * @return {Boolean} true if within range, otherwise false.
+     */
+    $D.validateMillisecond = function (value) {
+        return validate(value, 0, 999, "millisecond");
+    };
+
+    /**
+     * Validates the number is within an acceptable range for seconds [0-59].
+     * @param {Number}   The number to check if within range.
+     * @return {Boolean} true if within range, otherwise false.
+     */
+    $D.validateSecond = function (value) {
+        return validate(value, 0, 59, "second");
+    };
+
+    /**
+     * Validates the number is within an acceptable range for minutes [0-59].
+     * @param {Number}   The number to check if within range.
+     * @return {Boolean} true if within range, otherwise false.
+     */
+    $D.validateMinute = function (value) {
+        return validate(value, 0, 59, "minute");
+    };
+
+    /**
+     * Validates the number is within an acceptable range for hours [0-23].
+     * @param {Number}   The number to check if within range.
+     * @return {Boolean} true if within range, otherwise false.
+     */
+    $D.validateHour = function (value) {
+        return validate(value, 0, 23, "hour");
+    };
+
+    /**
+     * Validates the number is within an acceptable range for the days in a month [0-MaxDaysInMonth].
+     * @param {Number}   The number to check if within range.
+     * @return {Boolean} true if within range, otherwise false.
+     */
+    $D.validateDay = function (value, year, month) {
+        return validate(value, 1, $D.getDaysInMonth(year, month), "day");
+    };
+
+    /**
+     * Validates the number is within an acceptable range for months [0-11].
+     * @param {Number}   The number to check if within range.
+     * @return {Boolean} true if within range, otherwise false.
+     */
+    $D.validateMonth = function (value) {
+        return validate(value, 0, 11, "month");
+    };
+
+    /**
+     * Validates the number is within an acceptable range for years.
+     * @param {Number}   The number to check if within range.
+     * @return {Boolean} true if within range, otherwise false.
+     */
+    $D.validateYear = function (value) {
+        return validate(value, 0, 9999, "year");
+    };
+
+    /**
+     * Set the value of year, month, day, hour, minute, second, millisecond of date instance using given configuration object.
+     * Example
+    <pre><code>
+    Date.today().set( { day: 20, month: 1 } )
+
+    new Date().set( { millisecond: 0 } )
+    </code></pre>
+     * 
+     * @param {Object}   Configuration object containing attributes (month, day, etc.)
+     * @return {Date}    this
+     */
+    $P.set = function (config) {
+        if ($D.validateMillisecond(config.millisecond)) {
+            this.addMilliseconds(config.millisecond - this.getMilliseconds()); 
+        }
+        
+        if ($D.validateSecond(config.second)) {
+            this.addSeconds(config.second - this.getSeconds()); 
+        }
+        
+        if ($D.validateMinute(config.minute)) {
+            this.addMinutes(config.minute - this.getMinutes()); 
+        }
+        
+        if ($D.validateHour(config.hour)) {
+            this.addHours(config.hour - this.getHours()); 
+        }
+        
+        if ($D.validateMonth(config.month)) {
+            this.addMonths(config.month - this.getMonth()); 
+        }
+
+        if ($D.validateYear(config.year)) {
+            this.addYears(config.year - this.getFullYear()); 
+        }
+        
+	    /* day has to go last because you can't validate the day without first knowing the month */
+        if ($D.validateDay(config.day, this.getFullYear(), this.getMonth())) {
+            this.addDays(config.day - this.getDate()); 
+        }
+        
+        if (config.timezone) { 
+            this.setTimezone(config.timezone); 
+        }
+        
+        if (config.timezoneOffset) { 
+            this.setTimezoneOffset(config.timezoneOffset); 
+        }
+
+        if (config.week && validate(config.week, 0, 53, "week")) {
+            this.setWeek(config.week);
+        }
+        
+        return this;   
+    };
+
+    /**
+     * Moves the date to the first day of the month.
+     * @return {Date}    this
+     */
+    $P.moveToFirstDayOfMonth = function () {
+        return this.set({ day: 1 });
+    };
+
+    /**
+     * Moves the date to the last day of the month.
+     * @return {Date}    this
+     */
+    $P.moveToLastDayOfMonth = function () { 
+        return this.set({ day: $D.getDaysInMonth(this.getFullYear(), this.getMonth())});
+    };
+
+    /**
+     * Moves the date to the next n'th occurrence of the dayOfWeek starting from the beginning of the month. The number (-1) is a magic number and will return the last occurrence of the dayOfWeek in the month.
+     * @param {Number}   The dayOfWeek to move to
+     * @param {Number}   The n'th occurrence to move to. Use (-1) to return the last occurrence in the month
+     * @return {Date}    this
+     */
+    $P.moveToNthOccurrence = function (dayOfWeek, occurrence) {
+        var shift = 0;
+        if (occurrence > 0) {
+            shift = occurrence - 1;
+        }
+        else if (occurrence === -1) {
+            this.moveToLastDayOfMonth();
+            if (this.getDay() !== dayOfWeek) {
+                this.moveToDayOfWeek(dayOfWeek, -1);
+            }
+            return this;
+        }
+        return this.moveToFirstDayOfMonth().addDays(-1).moveToDayOfWeek(dayOfWeek, +1).addWeeks(shift);
+    };
+
+    /**
+     * Move to the next or last dayOfWeek based on the orient value.
+     * @param {Number}   The dayOfWeek to move to
+     * @param {Number}   Forward (+1) or Back (-1). Defaults to +1. [Optional]
+     * @return {Date}    this
+     */
+    $P.moveToDayOfWeek = function (dayOfWeek, orient) {
+        var diff = (dayOfWeek - this.getDay() + 7 * (orient || +1)) % 7;
+        return this.addDays((diff === 0) ? diff += 7 * (orient || +1) : diff);
+    };
+
+    /**
+     * Move to the next or last month based on the orient value.
+     * @param {Number}   The month to move to. 0 = January, 11 = December
+     * @param {Number}   Forward (+1) or Back (-1). Defaults to +1. [Optional]
+     * @return {Date}    this
+     */
+    $P.moveToMonth = function (month, orient) {
+        var diff = (month - this.getMonth() + 12 * (orient || +1)) % 12;
+        return this.addMonths((diff === 0) ? diff += 12 * (orient || +1) : diff);
+    };
+
+    /**
+     * Get the Ordinal day (numeric day number) of the year, adjusted for leap year.
+     * @return {Number} 1 through 365 (366 in leap years)
+     */
+    $P.getOrdinalNumber = function () {
+        return Math.ceil((this.clone().clearTime() - new Date(this.getFullYear(), 0, 1)) / 86400000) + 1;
+    };
+
+    /**
+     * Get the time zone abbreviation of the current date.
+     * @return {String} The abbreviated time zone name (e.g. "EST")
+     */
+    $P.getTimezone = function () {
+        return $D.getTimezoneAbbreviation(this.getUTCOffset());
+    };
+
+    $P.setTimezoneOffset = function (offset) {
+        var here = this.getTimezoneOffset(), there = Number(offset) * -6 / 10;
+        return this.addMinutes(there - here); 
+    };
+
+    $P.setTimezone = function (offset) { 
+        return this.setTimezoneOffset($D.getTimezoneOffset(offset)); 
+    };
+
+    /**
+     * Indicates whether Daylight Saving Time is observed in the current time zone.
+     * @return {Boolean} true|false
+     */
+    $P.hasDaylightSavingTime = function () { 
+        return (Date.today().set({month: 0, day: 1}).getTimezoneOffset() !== Date.today().set({month: 6, day: 1}).getTimezoneOffset());
+    };
+    
+    /**
+     * Indicates whether this Date instance is within the Daylight Saving Time range for the current time zone.
+     * @return {Boolean} true|false
+     */
+    $P.isDaylightSavingTime = function () {
+        return Date.today().set({month: 0, day: 1}).getTimezoneOffset() != this.getTimezoneOffset();
+    };
+
+    /**
+     * Get the offset from UTC of the current date.
+     * @return {String} The 4-character offset string prefixed with + or - (e.g. "-0500")
+     */
+    $P.getUTCOffset = function () {
+        var n = this.getTimezoneOffset() * -10 / 6, r;
+        if (n < 0) { 
+            r = (n - 10000).toString(); 
+            return r.charAt(0) + r.substr(2); 
+        } else { 
+            r = (n + 10000).toString();  
+            return "+" + r.substr(1); 
+        }
+    };
+
+    /**
+     * Returns the number of milliseconds between this date and date.
+     * @param {Date} Defaults to now
+     * @return {Number} The diff in milliseconds
+     */
+    $P.getElapsed = function (date) {
+        return (date || new Date()) - this;
+    };
+
+    if (!$P.toISOString) {
+        /**
+         * Converts the current date instance into a string with an ISO 8601 format. The date is converted to it's UTC value.
+         * @return {String}  ISO 8601 string of date
+         */
+        $P.toISOString = function () {
+            // From http://www.json.org/json.js. Public Domain. 
+            function f(n) {
+                return n < 10 ? '0' + n : n;
+            }
+
+            return '"' + this.getUTCFullYear()   + '-' +
+                f(this.getUTCMonth() + 1) + '-' +
+                f(this.getUTCDate())      + 'T' +
+                f(this.getUTCHours())     + ':' +
+                f(this.getUTCMinutes())   + ':' +
+                f(this.getUTCSeconds())   + 'Z"';
+        };
     }
-    return -1;
-};
-
-/**
- * Gets the day number (0-6) if given a CultureInfo specific string which is a valid dayName, abbreviatedDayName or shortestDayName (two char).
- * @param {String}   The name of the day (eg. "Monday, "Mon", "tuesday", "tue", "We", "we").
- * @return {Number}  The day number
- */
-Date.getDayNumberFromName = function (name) {
-    var n = Date.CultureInfo.dayNames, m = Date.CultureInfo.abbreviatedDayNames, o = Date.CultureInfo.shortestDayNames, s = name.toLowerCase();
-    for (var i = 0; i < n.length; i++) { 
-        if (n[i].toLowerCase() == s || m[i].toLowerCase() == s) { 
-            return i; 
-        }
-    }
-    return -1;  
-};
-
-/**
- * Determines if the current date instance is within a LeapYear.
- * @param {Number}   The year (0-9999).
- * @return {Boolean} true if date is within a LeapYear, otherwise false.
- */
-Date.isLeapYear = function (year) { 
-    return (((year % 4 === 0) && (year % 100 !== 0)) || (year % 400 === 0)); 
-};
-
-/**
- * Gets the number of days in the month, given a year and month value. Automatically corrects for LeapYear.
- * @param {Number}   The year (0-9999).
- * @param {Number}   The month (0-11).
- * @return {Number}  The number of days in the month.
- */
-Date.getDaysInMonth = function (year, month) {
-    return [31, (Date.isLeapYear(year) ? 29 : 28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month];
-};
-
-Date.getTimezoneOffset = function (s, dst) {
-    return (dst || false) ? Date.CultureInfo.abbreviatedTimeZoneDST[s.toUpperCase()] :
-        Date.CultureInfo.abbreviatedTimeZoneStandard[s.toUpperCase()];
-};
-
-Date.getTimezoneAbbreviation = function (offset, dst) {
-    var n = (dst || false) ? Date.CultureInfo.abbreviatedTimeZoneDST : Date.CultureInfo.abbreviatedTimeZoneStandard, p;
-    for (p in n) { 
-        if (n[p] === offset) { 
-            return p; 
-        }
-    }
-    return null;
-};
-
-/**
- * Returns a new Date object that is an exact date and time copy of the original instance.
- * @return {Date}    A new Date instance
- */
-Date.prototype.clone = function () {
-    return new Date(this.getTime()); 
-};
-
-/**
- * Compares this instance to a Date object and return an number indication of their relative values.  
- * @param {Date}     Date object to compare [Required]
- * @return {Number}  1 = this is greaterthan date. -1 = this is lessthan date. 0 = values are equal
- */
-Date.prototype.compareTo = function (date) {
-    if (isNaN(this)) { 
-        throw new Error(this); 
-    }
-    if (date instanceof Date && !isNaN(date)) {
-        return (this > date) ? 1 : (this < date) ? -1 : 0;
-    } else { 
-        throw new TypeError(date); 
-    }
-};
-
-/**
- * Compares this instance to another Date object and returns true if they are equal.  
- * @param {Date}     Date object to compare [Required]
- * @return {Boolean} true if dates are equal. false if they are not equal.
- */
-Date.prototype.equals = function (date) { 
-    return (this.compareTo(date) === 0); 
-};
-
-/**
- * Determines is this instance is between a range of two dates or equal to either the start or end dates.
- * @param {Date}     Start of range [Required]
- * @param {Date}     End of range [Required]
- * @return {Boolean} true is this is between or equal to the start and end dates, else false
- */
-Date.prototype.between = function (start, end) {
-    var t = this.getTime();
-    return t >= start.getTime() && t <= end.getTime();
-};
-
-/**
- * Adds the specified number of milliseconds to this instance. 
- * @param {Number}   The number of milliseconds to add. The number can be positive or negative [Required]
- * @return {Date}    this
- */
-Date.prototype.addMilliseconds = function (value) {
-    this.setMilliseconds(this.getMilliseconds() + value);
-    return this;
-};
-
-/**
- * Adds the specified number of seconds to this instance. 
- * @param {Number}   The number of seconds to add. The number can be positive or negative [Required]
- * @return {Date}    this
- */
-Date.prototype.addSeconds = function (value) { 
-    return this.addMilliseconds(value * 1000); 
-};
-
-/**
- * Adds the specified number of seconds to this instance. 
- * @param {Number}   The number of seconds to add. The number can be positive or negative [Required]
- * @return {Date}    this
- */
-Date.prototype.addMinutes = function (value) { 
-    return this.addMilliseconds(value * 60000); /* 60*1000 */
-};
-
-/**
- * Adds the specified number of hours to this instance. 
- * @param {Number}   The number of hours to add. The number can be positive or negative [Required]
- * @return {Date}    this
- */
-Date.prototype.addHours = function (value) { 
-    return this.addMilliseconds(value * 3600000); /* 60*60*1000 */
-};
-
-/**
- * Adds the specified number of days to this instance. 
- * @param {Number}   The number of days to add. The number can be positive or negative [Required]
- * @return {Date}    this
- */
-Date.prototype.addDays = function (value) { 
-    return this.addMilliseconds(value * 86400000); /* 60*60*24*1000 */
-};
-
-/**
- * Adds the specified number of weeks to this instance. 
- * @param {Number}   The number of weeks to add. The number can be positive or negative [Required]
- * @return {Date}    this
- */
-Date.prototype.addWeeks = function (value) { 
-    return this.addMilliseconds(value * 604800000); /* 60*60*24*7*1000 */
-};
-
-/**
- * Adds the specified number of months to this instance. 
- * @param {Number}   The number of months to add. The number can be positive or negative [Required]
- * @return {Date}    this
- */
-Date.prototype.addMonths = function (value) {
-    var n = this.getDate();
-    this.setDate(1);
-    this.setMonth(this.getMonth() + value);
-    this.setDate(Math.min(n, this.getDaysInMonth()));
-    return this;
-};
-
-/**
- * Adds the specified number of years to this instance. 
- * @param {Number}   The number of years to add. The number can be positive or negative [Required]
- * @return {Date}    this
- */
-Date.prototype.addYears = function (value) {
-    return this.addMonths(value * 12);
-};
-
-/**
- * Adds (or subtracts) to the value of the year, month, day, hour, minute, second, millisecond of the date instance using given configuration object. Positive and Negative values allowed.
- * Example
-<pre><code>
-Date.today().add( { day: 1, month: 1 } )
- 
-new Date().add( { year: -1 } )
-</code></pre> 
- * @param {Object}   Configuration object containing attributes (month, day, etc.)
- * @return {Date}    this
- */
-Date.prototype.add = function (config) {
-    if (typeof config == "number") {
-        this._orient = config;
-        return this;    
-    }
-    var x = config;
-    if (x.millisecond || x.milliseconds) { 
-        this.addMilliseconds(x.millisecond || x.milliseconds); 
-    }
-    if (x.second || x.seconds) { 
-        this.addSeconds(x.second || x.seconds); 
-    }
-    if (x.minute || x.minutes) { 
-        this.addMinutes(x.minute || x.minutes); 
-    }
-    if (x.hour || x.hours) { 
-        this.addHours(x.hour || x.hours); 
-    }
-    if (x.month || x.months) { 
-        this.addMonths(x.month || x.months); 
-    }
-    if (x.year || x.years) { 
-        this.addYears(x.year || x.years); 
-    }
-    if (x.day || x.days) {
-        this.addDays(x.day || x.days); 
-    }
-    return this;
-};
-
-// private
-Date._validate = function (value, min, max, name) {
-    if (typeof value != "number") {
-        throw new TypeError(value + " is not a Number."); 
-    } else if (value < min || value > max) {
-        throw new RangeError(value + " is not a valid value for " + name + "."); 
-    }
-    return true;
-};
-
-/**
- * Validates the number is within an acceptable range for milliseconds [0-999].
- * @param {Number}   The number to check if within range.
- * @return {Boolean} true if within range, otherwise false.
- */
-Date.validateMillisecond = function (n) {
-    return Date._validate(n, 0, 999, "milliseconds");
-};
-
-/**
- * Validates the number is within an acceptable range for seconds [0-59].
- * @param {Number}   The number to check if within range.
- * @return {Boolean} true if within range, otherwise false.
- */
-Date.validateSecond = function (n) {
-    return Date._validate(n, 0, 59, "seconds");
-};
-
-/**
- * Validates the number is within an acceptable range for minutes [0-59].
- * @param {Number}   The number to check if within range.
- * @return {Boolean} true if within range, otherwise false.
- */
-Date.validateMinute = function (n) {
-    return Date._validate(n, 0, 59, "minutes");
-};
-
-/**
- * Validates the number is within an acceptable range for hours [0-23].
- * @param {Number}   The number to check if within range.
- * @return {Boolean} true if within range, otherwise false.
- */
-Date.validateHour = function (n) {
-    return Date._validate(n, 0, 23, "hours");
-};
-
-/**
- * Validates the number is within an acceptable range for the days in a month [0-MaxDaysInMonth].
- * @param {Number}   The number to check if within range.
- * @return {Boolean} true if within range, otherwise false.
- */
-Date.validateDay = function (n, year, month) {
-    return Date._validate(n, 1, Date.getDaysInMonth(year, month), "days");
-};
-
-/**
- * Validates the number is within an acceptable range for months [0-11].
- * @param {Number}   The number to check if within range.
- * @return {Boolean} true if within range, otherwise false.
- */
-Date.validateMonth = function (n) {
-    return Date._validate(n, 0, 11, "months");
-};
-
-/**
- * Validates the number is within an acceptable range for years [0-9999].
- * @param {Number}   The number to check if within range.
- * @return {Boolean} true if within range, otherwise false.
- */
-Date.validateYear = function (n) {
-    return Date._validate(n, 1, 9999, "seconds");
-};
-
-/**
- * Set the value of year, month, day, hour, minute, second, millisecond of date instance using given configuration object.
- * Example
-<pre><code>
-Date.today().set( { day: 20, month: 1 } )
-
-new Date().set( { millisecond: 0 } )
-</code></pre>
- * 
- * @param {Object}   Configuration object containing attributes (month, day, etc.)
- * @return {Date}    this
- */
-Date.prototype.set = function (config) {
-    var x = config;
-
-    if (!x.millisecond && x.millisecond !== 0) { 
-        x.millisecond = -1; 
-    }
-    if (!x.second && x.second !== 0) { 
-        x.second = -1; 
-    }
-    if (!x.minute && x.minute !== 0) { 
-        x.minute = -1; 
-    }
-    if (!x.hour && x.hour !== 0) { 
-        x.hour = -1; 
-    }
-    if (!x.day && x.day !== 0) { 
-        x.day = -1; 
-    }
-    if (!x.month && x.month !== 0) { 
-        x.month = -1; 
-    }
-    if (!x.year && x.year !== 0) { 
-        x.year = -1; 
-    }
-
-    if (x.millisecond != -1 && Date.validateMillisecond(x.millisecond)) {
-        this.addMilliseconds(x.millisecond - this.getMilliseconds()); 
-    }
-    if (x.second != -1 && Date.validateSecond(x.second)) {
-        this.addSeconds(x.second - this.getSeconds()); 
-    }
-    if (x.minute != -1 && Date.validateMinute(x.minute)) {
-        this.addMinutes(x.minute - this.getMinutes()); 
-    }
-    if (x.hour != -1 && Date.validateHour(x.hour)) {
-        this.addHours(x.hour - this.getHours()); 
-    }
-    if (x.month !== -1 && Date.validateMonth(x.month)) {
-        this.addMonths(x.month - this.getMonth()); 
-    }
-    if (x.year != -1 && Date.validateYear(x.year)) {
-        this.addYears(x.year - this.getFullYear()); 
-    }
-    
-	/* day has to go last because you can't validate the day without first knowing the month */
-    if (x.day != -1 && Date.validateDay(x.day, this.getFullYear(), this.getMonth())) {
-        this.addDays(x.day - this.getDate()); 
-    }
-    if (x.timezone) { 
-        this.setTimezone(x.timezone); 
-    }
-    if (x.timezoneOffset) { 
-        this.setTimezoneOffset(x.timezoneOffset); 
-    }
-    
-    return this;   
-};
-
-/**
- * Resets the time of this Date object to 12:00 AM (00:00), which is the start of the day.
- * @return {Date}    this
- */
-Date.prototype.clearTime = function () {
-    this.setHours(0); 
-    this.setMinutes(0); 
-    this.setSeconds(0);
-    this.setMilliseconds(0); 
-    return this;
-};
-
-/**
- * Determines whether or not this instance is in a leap year.
- * @return {Boolean} true if this instance is in a leap year, else false
- */
-Date.prototype.isLeapYear = function () { 
-    var y = this.getFullYear(); 
-    return (((y % 4 === 0) && (y % 100 !== 0)) || (y % 400 === 0)); 
-};
-
-/**
- * Determines whether or not this instance is a weekday.
- * @return {Boolean} true if this instance is a weekday
- */
-Date.prototype.isWeekday = function () { 
-    return !(this.is().sat() || this.is().sun());
-};
-
-/**
- * Get the number of days in the current month, adjusted for leap year.
- * @return {Number}  The number of days in the month
- */
-Date.prototype.getDaysInMonth = function () { 
-    return Date.getDaysInMonth(this.getFullYear(), this.getMonth());
-};
-
-/**
- * Moves the date to the first day of the month.
- * @return {Date}    this
- */
-Date.prototype.moveToFirstDayOfMonth = function () {
-    return this.set({ day: 1 });
-};
-
-/**
- * Moves the date to the last day of the month.
- * @return {Date}    this
- */
-Date.prototype.moveToLastDayOfMonth = function () { 
-    return this.set({ day: this.getDaysInMonth()});
-};
-
-/**
- * Move to the next or last dayOfWeek based on the orient value.
- * @param {Number}   The dayOfWeek to move to.
- * @param {Number}   Forward (+1) or Back (-1). Defaults to +1. [Optional]
- * @return {Date}    this
- */
-Date.prototype.moveToDayOfWeek = function (day, orient) {
-    var diff = (day - this.getDay() + 7 * (orient || +1)) % 7;
-    return this.addDays((diff === 0) ? diff += 7 * (orient || +1) : diff);
-};
-
-/**
- * Move to the next or last month based on the orient value.
- * @param {Number}   The month to move to. 0 = January, 11 = December.
- * @param {Number}   Forward (+1) or Back (-1). Defaults to +1. [Optional]
- * @return {Date}    this
- */
-Date.prototype.moveToMonth = function (month, orient) {
-    var diff = (month - this.getMonth() + 12 * (orient || +1)) % 12;
-    return this.addMonths((diff === 0) ? diff += 12 * (orient || +1) : diff);
-};
-
-/**
- * Get the numeric day number of the year, adjusted for leap year.
- * @return {Number} 0 through 364 (365 in leap years)
- */
-Date.prototype.getDayOfYear = function () {
-    return Math.floor((this - new Date(this.getFullYear(), 0, 1)) / 86400000);
-};
-
-/**
- * Get the week of the year for the current date instance.
- * @param {Number}   A Number that represents the first day of the week (0-6) [Optional]
- * @return {Number}  0 through 53
- */
-Date.prototype.getWeekOfYear = function (firstDayOfWeek) {
-    var y = this.getFullYear(), m = this.getMonth(), d = this.getDate();
-    
-    var dow = firstDayOfWeek || Date.CultureInfo.firstDayOfWeek;
-	
-    var offset = 7 + 1 - new Date(y, 0, 1).getDay();
-    if (offset == 8) {
-        offset = 1;
-    }
-    var daynum = ((Date.UTC(y, m, d, 0, 0, 0) - Date.UTC(y, 0, 1, 0, 0, 0)) / 86400000) + 1;
-    var w = Math.floor((daynum - offset + 7) / 7);
-    if (w === dow) {
-        y--;
-        var prevOffset = 7 + 1 - new Date(y, 0, 1).getDay();
-        if (prevOffset == 2 || prevOffset == 8) { 
-            w = 53; 
-        } else { 
-            w = 52; 
-        }
-    }
-    return w;
-};
-
-/**
- * Determine whether Daylight Saving Time (DST) is in effect
- * @return {Boolean} True if DST is in effect.
- */
-Date.prototype.isDST = function () {
-    console.log('isDST');
-    /* TODO: not sure if this is portable ... get from Date.CultureInfo? */
-    return this.toString().match(/(E|C|M|P)(S|D)T/)[2] == "D";
-};
-
-/**
- * Get the timezone abbreviation of the current date.
- * @return {String} The abbreviated timezone name (e.g. "EST")
- */
-Date.prototype.getTimezone = function () {
-    return Date.getTimezoneAbbreviation(this.getUTCOffset, this.isDST());
-};
-
-Date.prototype.setTimezoneOffset = function (s) {
-    var here = this.getTimezoneOffset(), there = Number(s) * -6 / 10;
-    this.addMinutes(there - here); 
-    return this;
-};
-
-Date.prototype.setTimezone = function (s) { 
-    return this.setTimezoneOffset(Date.getTimezoneOffset(s)); 
-};
-
-/**
- * Get the offset from UTC of the current date.
- * @return {String} The 4-character offset string prefixed with + or - (e.g. "-0500")
- */
-Date.prototype.getUTCOffset = function () {
-    var n = this.getTimezoneOffset() * -10 / 6, r;
-    if (n < 0) { 
-        r = (n - 10000).toString(); 
-        return r[0] + r.substr(2); 
-    } else { 
-        r = (n + 10000).toString();  
-        return "+" + r.substr(1); 
-    }
-};
-
-/**
- * Gets the name of the day of the week.
- * @param {Boolean}  true to return the abbreviated name of the day of the week
- * @return {String}  The name of the day
- */
-Date.prototype.getDayName = function (abbrev) {
-    return abbrev ? Date.CultureInfo.abbreviatedDayNames[this.getDay()] : 
-        Date.CultureInfo.dayNames[this.getDay()];
-};
-
-/**
- * Gets the month name.
- * @param {Boolean}  true to return the abbreviated name of the month
- * @return {String}  The name of the month
- */
-Date.prototype.getMonthName = function (abbrev) {
-    return abbrev ? Date.CultureInfo.abbreviatedMonthNames[this.getMonth()] : 
-        Date.CultureInfo.monthNames[this.getMonth()];
-};
-
-// private
-Date.prototype._toString = Date.prototype.toString;
-
-/**
- * Converts the value of the current Date object to its equivalent string representation.
- * Format Specifiers
-<pre>
-Format  Description                                                                  Example
-------  ---------------------------------------------------------------------------  -----------------------
- s      The seconds of the minute between 1-59.                                      "1" to "59"
- ss     The seconds of the minute with leading zero if required.                     "01" to "59"
- 
- m      The minute of the hour between 0-59.                                         "1"  or "59"
- mm     The minute of the hour with leading zero if required.                        "01" or "59"
- 
- h      The hour of the day between 1-12.                                            "1"  to "12"
- hh     The hour of the day with leading zero if required.                           "01" to "12"
- 
- H      The hour of the day between 1-23.                                            "1"  to "23"
- HH     The hour of the day with leading zero if required.                           "01" to "23"
- 
- d      The day of the month between 1 and 31.                                       "1"  to "31"
- dd     The day of the month with leading zero if required.                          "01" to "31"
- ddd    Abbreviated day name. Date.CultureInfo.abbreviatedDayNames.                  "Mon" to "Sun" 
- dddd   The full day name. Date.CultureInfo.dayNames.                                "Monday" to "Sunday"
- 
- M      The month of the year between 1-12.                                          "1" to "12"
- MM     The month of the year with leading zero if required.                         "01" to "12"
- MMM    Abbreviated month name. Date.CultureInfo.abbreviatedMonthNames.              "Jan" to "Dec"
- MMMM   The full month name. Date.CultureInfo.monthNames.                            "January" to "December"
-
- yy     Displays the year as a maximum two-digit number.                             "99" or "07"
- yyyy   Displays the full four digit year.                                           "1999" or "2007"
- 
- t      Displays the first character of the A.M./P.M. designator.                    "A" or "P"
-        Date.CultureInfo.amDesignator or Date.CultureInfo.pmDesignator
- tt     Displays the A.M./P.M. designator.                                           "AM" or "PM"
-        Date.CultureInfo.amDesignator or Date.CultureInfo.pmDesignator
-</pre>
- * @param {String}   A format string consisting of one or more format spcifiers [Optional].
- * @return {String}  A string representation of the current Date object.
- */
-Date.prototype.toString = function (format) {
-    var self = this;
-
-    var p = function p(s) {
-        return (s.toString().length == 1) ? "0" + s : s;
-    };
-
-    return format ? format.replace(/dd?d?d?|MM?M?M?|yy?y?y?|hh?|HH?|mm?|ss?|tt?|zz?z?/g, 
-    function (format) {
-        switch (format) {
-        case "hh":
-            return p(self.getHours() < 13 ? self.getHours() : (self.getHours() - 12));
-        case "h":
-            return self.getHours() < 13 ? self.getHours() : (self.getHours() - 12);
-        case "HH":
-            return p(self.getHours());
-        case "H":
-            return self.getHours();
-        case "mm":
-            return p(self.getMinutes());
-        case "m":
-            return self.getMinutes();
-        case "ss":
-            return p(self.getSeconds());
-        case "s":
-            return self.getSeconds();
-        case "yyyy":
-            return self.getFullYear();
-        case "yy":
-            return self.getFullYear().toString().substring(2, 4);
-        case "dddd":
-            return self.getDayName();
-        case "ddd":
-            return self.getDayName(true);
-        case "dd":
-            return p(self.getDate());
-        case "d":
-            return self.getDate().toString();
-        case "MMMM":
-            return self.getMonthName();
-        case "MMM":
-            return self.getMonthName(true);
-        case "MM":
-            return p((self.getMonth() + 1));
-        case "M":
-            return self.getMonth() + 1;
-        case "t":
-            return self.getHours() < 12 ? Date.CultureInfo.amDesignator.substring(0, 1) : Date.CultureInfo.pmDesignator.substring(0, 1);
-        case "tt":
-            return self.getHours() < 12 ? Date.CultureInfo.amDesignator : Date.CultureInfo.pmDesignator;
-        case "zzz":
-        case "zz":
-        case "z":
-            return "";
-        }
-    }
-    ) : this._toString();
-};
+    
+    // private
+    $P._toString = $P.toString;
+
+    /**
+     * Converts the value of the current Date object to its equivalent string representation.
+     * Format Specifiers
+    <pre>
+    CUSTOM DATE AND TIME FORMAT STRINGS
+    Format  Description                                                                  Example
+    ------  ---------------------------------------------------------------------------  -----------------------
+     s      The seconds of the minute between 0-59.                                      "0" to "59"
+     ss     The seconds of the minute with leading zero if required.                     "00" to "59"
+     
+     m      The minute of the hour between 0-59.                                         "0"  or "59"
+     mm     The minute of the hour with leading zero if required.                        "00" or "59"
+     
+     h      The hour of the day between 1-12.                                            "1"  to "12"
+     hh     The hour of the day with leading zero if required.                           "01" to "12"
+     
+     H      The hour of the day between 0-23.                                            "0"  to "23"
+     HH     The hour of the day with leading zero if required.                           "00" to "23"
+     
+     d      The day of the month between 1 and 31.                                       "1"  to "31"
+     dd     The day of the month with leading zero if required.                          "01" to "31"
+     ddd    Abbreviated day name. $C.abbreviatedDayNames.                                "Mon" to "Sun" 
+     dddd   The full day name. $C.dayNames.                                              "Monday" to "Sunday"
+     
+     M      The month of the year between 1-12.                                          "1" to "12"
+     MM     The month of the year with leading zero if required.                         "01" to "12"
+     MMM    Abbreviated month name. $C.abbreviatedMonthNames.                            "Jan" to "Dec"
+     MMMM   The full month name. $C.monthNames.                                          "January" to "December"
+
+     yy     The year as a two-digit number.                                              "99" or "08"
+     yyyy   The full four digit year.                                                    "1999" or "2008"
+     
+     t      Displays the first character of the A.M./P.M. designator.                    "A" or "P"
+            $C.amDesignator or $C.pmDesignator
+     tt     Displays the A.M./P.M. designator.                                           "AM" or "PM"
+            $C.amDesignator or $C.pmDesignator
+     
+     S      The ordinal suffix ("st, "nd", "rd" or "th") of the current day.            "st, "nd", "rd" or "th"
+
+|| *Format* || *Description* || *Example* ||
+|| d      || The CultureInfo shortDate Format Pattern                                     || "M/d/yyyy" ||
+|| D      || The CultureInfo longDate Format Pattern                                      || "dddd, MMMM dd, yyyy" ||
+|| F      || The CultureInfo fullDateTime Format Pattern                                  || "dddd, MMMM dd, yyyy h:mm:ss tt" ||
+|| m      || The CultureInfo monthDay Format Pattern                                      || "MMMM dd" ||
+|| r      || The CultureInfo rfc1123 Format Pattern                                       || "ddd, dd MMM yyyy HH:mm:ss GMT" ||
+|| s      || The CultureInfo sortableDateTime Format Pattern                              || "yyyy-MM-ddTHH:mm:ss" ||
+|| t      || The CultureInfo shortTime Format Pattern                                     || "h:mm tt" ||
+|| T      || The CultureInfo longTime Format Pattern                                      || "h:mm:ss tt" ||
+|| u      || The CultureInfo universalSortableDateTime Format Pattern                     || "yyyy-MM-dd HH:mm:ssZ" ||
+|| y      || The CultureInfo yearMonth Format Pattern                                     || "MMMM, yyyy" ||
+     
+
+    STANDARD DATE AND TIME FORMAT STRINGS
+    Format  Description                                                                  Example ("en-US")
+    ------  ---------------------------------------------------------------------------  -----------------------
+     d      The CultureInfo shortDate Format Pattern                                     "M/d/yyyy"
+     D      The CultureInfo longDate Format Pattern                                      "dddd, MMMM dd, yyyy"
+     F      The CultureInfo fullDateTime Format Pattern                                  "dddd, MMMM dd, yyyy h:mm:ss tt"
+     m      The CultureInfo monthDay Format Pattern                                      "MMMM dd"
+     r      The CultureInfo rfc1123 Format Pattern                                       "ddd, dd MMM yyyy HH:mm:ss GMT"
+     s      The CultureInfo sortableDateTime Format Pattern                              "yyyy-MM-ddTHH:mm:ss"
+     t      The CultureInfo shortTime Format Pattern                                     "h:mm tt"
+     T      The CultureInfo longTime Format Pattern                                      "h:mm:ss tt"
+     u      The CultureInfo universalSortableDateTime Format Pattern                     "yyyy-MM-dd HH:mm:ssZ"
+     y      The CultureInfo yearMonth Format Pattern                                     "MMMM, yyyy"
+    </pre>
+     * @param {String}   A format string consisting of one or more format spcifiers [Optional].
+     * @return {String}  A string representation of the current Date object.
+     */
+    $P.toString = function (format) {
+        var x = this;
+        
+        // Standard Date and Time Format Strings. Formats pulled from CultureInfo file and
+        // may vary by culture. 
+        if (format && format.length == 1) {
+            var c = $C.formatPatterns;
+            x.t = x.toString;
+            switch (format) {
+            case "d": 
+                return x.t(c.shortDate);
+            case "D":
+                return x.t(c.longDate);
+            case "F":
+                return x.t(c.fullDateTime);
+            case "m":
+                return x.t(c.monthDay);
+            case "r":
+                return x.t(c.rfc1123);
+            case "s":
+                return x.t(c.sortableDateTime);
+            case "t":
+                return x.t(c.shortTime);
+            case "T":
+                return x.t(c.longTime);
+            case "u":
+                return x.t(c.universalSortableDateTime);
+            case "y":
+                return x.t(c.yearMonth);
+            }    
+        }
+        
+        var ord = function (n) {
+                switch (n * 1) {
+                case 1: 
+                case 21: 
+                case 31: 
+                    return "st";
+                case 2: 
+                case 22: 
+                    return "nd";
+                case 3: 
+                case 23: 
+                    return "rd";
+                default: 
+                    return "th";
+                }
+            };
+        
+        return format ? format.replace(/(\\)?(dd?d?d?|MM?M?M?|yy?y?y?|hh?|HH?|mm?|ss?|tt?|S)/g, 
+        function (m) {
+            if (m.charAt(0) === "\\") {
+                return m.replace("\\", "");
+            }
+            x.h = x.getHours;
+            switch (m) {
+            case "hh":
+                return p(x.h() < 13 ? (x.h() === 0 ? 12 : x.h()) : (x.h() - 12));
+            case "h":
+                return x.h() < 13 ? (x.h() === 0 ? 12 : x.h()) : (x.h() - 12);
+            case "HH":
+                return p(x.h());
+            case "H":
+                return x.h();
+            case "mm":
+                return p(x.getMinutes());
+            case "m":
+                return x.getMinutes();
+            case "ss":
+                return p(x.getSeconds());
+            case "s":
+                return x.getSeconds();
+            case "yyyy":
+                return p(x.getFullYear(), 4);
+            case "yy":
+                return p(x.getFullYear());
+            case "dddd":
+                return $C.dayNames[x.getDay()];
+            case "ddd":
+                return $C.abbreviatedDayNames[x.getDay()];
+            case "dd":
+                return p(x.getDate());
+            case "d":
+                return x.getDate();
+            case "MMMM":
+                return $C.monthNames[x.getMonth()];
+            case "MMM":
+                return $C.abbreviatedMonthNames[x.getMonth()];
+            case "MM":
+                return p((x.getMonth() + 1));
+            case "M":
+                return x.getMonth() + 1;
+            case "t":
+                return x.h() < 12 ? $C.amDesignator.substring(0, 1) : $C.pmDesignator.substring(0, 1);
+            case "tt":
+                return x.h() < 12 ? $C.amDesignator : $C.pmDesignator;
+            case "S":
+                return ord(x.getDate());
+            default: 
+                return m;
+            }
+        }
+        ) : this._toString();
+    };
+}());    
