/**
 * @name        Global Utilities
 * @overview    An automated documentation publishing system for JavaScript.
 * @version        0.1
 * @revision    2007-06-01 00:00:00
 * @author        Michael Ord <a href="mailto:michael.ord@think.eu">michael.ord@think.eu</a>
 */
/**
 * @function    Array.push
 * @description    Simulates the Array.push() method for browssers that don't support it natively
 * @return        {Number} The current length of the array
 */
if (!Array.prototype.push){
    Array.prototype.push = function () {
        for (var i = 0; i < arguments.length; i++) {
            this [ this.length ] = arguments [ i ];
        };
        return this.length;
    };
};
/**
 * @function    Array.trim
 * @description    Trims spaces from the start and end of a string
 * @return        {String} The trimmed string
 */
if (!String.prototype.trim) {
    String.prototype.trim = function () {
        return this.replace (/^\s*/,'').replace(/\s*$/, '');
    };
};
/**
 * @function    Array.reverse
 * @description    DESCRIPTION HERE
 * @return        {String} The reversed string
 */
String.prototype.reverse = function () {
    var s    = '';
    for ( var i = this.length - 1; i >= 0; i-- ) {
        s    += this.charAt ( i );
    };
    return s;
};
/**
 * @function    String.normalize
 * @description    Removes double spaces from a string
 * @retutn        {String} The newly formatted string
 */
String.prototype.normalize = function () {
    return this.replace (/\s+/g, " ");
};
/**
 * @function    Date.isLeapYear
 * @description    DESCRIPTION HERE
 * @return        {Boolean}
 */
Date.prototype.isLeapYear = function () {
    var year    = this.getFullYear ();
    return ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0);
};
/**
 * @function    Date.getDaysInMonth
 * @description    DESCRIPTION HERE
 * @return        {Number}
 */
Date.prototype.getDaysInMonth = function () {
    var days    = new Array (31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
    if (this.isLeapYear ()){
        days [ 1 ]    = 29;
    };
    return days [ this.getMonth () ];
};
/**
 * @function    Date.isValid
 * @description    DESCRIPTION HERE
 * @param        {Number} YYYY
 * @param        {Number} MM
 * @param        {Number} DD
 * @return        {Boolean}
 */
Date.prototype.isValid = function (YYYY, MM, DD) {
    DD    = Number (DD);
    MM    = Number (MM);
    YYYY    = Number (YYYY);
    if (MM >= 0 && MM < 12 && String (YYYY).length == 4 && DD > 0) {
        var tmp    = new Date (YYYY, MM);
        var days    = tmp.getDaysInMonth ();
        if (DD <= tmp.getDaysInMonth ())    {
            return true;
        };
    };
    return false;
};
/**
 * @function    Date.getDiffMonths
 * @description    DESCRIPTION HERE
 * @param        {Object} to
 * @return        {Number}
 */
Date.prototype.getDiffMonths = function (to) {
    return this.dateDiff ("m", to);
};
/**
 * @function    Date.getDiffYears
 * @description    DESCRIPTION HERE
 * @param        {Object} to
 * @return        {Number}
 */
Date.prototype.getDiffYears = function (to) {
    return this.dateDiff ("y", to);
};
/**
 * @function    Date.dateDiff
 * @description    DESCRIPTION HERE
 * @param        {Object} to
 * @param        {Object} v_date
 * @return        {Number}
 */
Date.prototype.dateDiff = function (dp, v_date) {
    var ms    = v_date - this;
    var ss    = Math.floor (ms / 1000);
    var mm    = Math.floor (ss / 60);
    var hh    = Math.floor (mm / 60);
    var dd    = Math.floor (hh / 24);
    var yy    = Math.floor (dd / 365.25);
    var mn    = Math.floor (dd / 365.25 * 12);
    return (dp == "y") ? yy : (dp == "m") ? mn : (dp == "d") ? dd : (dp == "h") ? hh : (dp == "n") ? mm : (dp == "s") ? ss : ms;
};