/***********************************************************************************************************************************
 * Tuneo a clase Date
 */
Object.extend(Date, {
    _DiasMes: new Array(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31),

    _NombresMes: new Array('Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio', 'Julio', 'Agosto', 'Septiembre', 'Octubre', 'Noviembre', 'Diciembre'),
    _ANombresMes: new Array('Ene', 'Feb', 'Mar', 'Abr', 'May', 'Jun', 'Jul', 'Ago', 'Sep', 'Oct', 'Nov', 'Dic'),

    _NombresDias: new Array('Domingo', 'Lunes', 'Martes', 'Miércoles', 'Jueves', 'Viernes', 'Sábado', 'Domingo'),
    _ANombresDias: new Array('Dom', 'Lun', 'Mar', 'Mié', 'Jue', 'Vie', 'Sáb', 'Dom'),

    // Constantes utilizadas para los cálculos de tiempo
    SECOND:      1000, // milisegundos
    MINUTE:     60000,
    HOUR:     3600000,
    DAY:     86400000,
    WEEK:   604800000,

    /**
     * Método estático que nos permite convertir una cadena en una fecha según una cadena de formato dada.
     *
     * @param String str    Cadena que se pretende convertir a fecha.
     * @param String fmt    Cadena que indica el formato en el que se recibe la cadena de fecha. En esta cadena de formato se puede
     *                      indicar el formato con los siguientes carácteres:
     *                      <ul>
     *                          <li><strong>%d, %e:</strong> El día del mes.</li>
     *                          <li><strong>%m:</strong> El número del mes.</li>
     *                          <li><strong>%Y, %y:</strong> El número del año.</li>
     *                          <li><strong>%H, %I, %k, %l:</trong> El numero de la hora.</li>
     *                          <li><strong>%P, %p:</strong> La cadena de tarde  o mañana (PM/AM o pm/am).</li>
     *                          <li><strong>%M:</strong> El número de minutos.</li>
     *                          <li><strong>%S, %s:</strong> El número de segundos.</li>
     *                      </ul>
     *
     * @return Date         Esta función devuelve un objeto de tipo Fecha/Hora.
     */
    parseDate: function(str, fmt) {
        var today = new Date();
        var y = -1;
        var m = -1;
        var d = -1;
        var hr = -1;
        var min = -1;
        var s = -1;
        var a = str.split(/\W+/);
        var b = fmt.match(/%./g);
        var i = 0;
        for (i = 0; i < a.length; ++i) {
            if (!a[i]) continue;
            switch (b[i]) {
                case "%d": case "%e":
                    d = parseInt(a[i], 10);
                    break;

                case "%m":
                    m = parseInt(a[i], 10) - 1;
                    break;

                case "%Y": case "%y":
                    y = parseInt(a[i], 10);
                    if (y < 100) {
                        y+= (y > 29? 1900: 2000);
                    }
                    break;

                case "%H": case "%I": case "%k": case "%l":
                    hr = parseInt(a[i], 10);
                    break;

                case "%P": case "%p":
                    if (/pm/i.test(a[i]) && hr < 12) {
                        hr += 12;
                    } else if (/am/i.test(a[i]) && hr >= 12) {
                        hr -= 12;
                    }
                    break;

                case "%M":
                    min = parseInt(a[i], 10);
                    break;

                case "%S": case "%s":
                    s = parseInt(a[i], 10);
                    break;
            }
        }

        // Si alguno de los valores obtenidos NO es válido, se asignan los de la fecha/hora actuales.
        if (isNaN(y)||(y == -1)) y = today.getFullYear();
        if (isNaN(m)||(m == -1)) m = today.getMonth();
        if (isNaN(d)||(d == -1)) d = today.getDate();
        if (isNaN(hr)||(hr == -1)) hr = today.getHours();
        if (isNaN(min)||(min == -1)) min = today.getMinutes();
        if (isNaN(s)||(s == -1)) s = today.getSeconds();

        return new Date(y, m, d, hr, min, s, 0);
    }
});

/*/
Date._DiasMes = new Array(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);

Date._NombresMes = new Array('Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio', 'Julio', 'Agosto', 'Septiembre', 'Octubre', 'Noviembre', 'Diciembre');
Date._ANombresMes = new Array('Ene', 'Feb', 'Mar', 'Abr', 'May', 'Jun', 'Jul', 'Ago', 'Sep', 'Oct', 'Nov', 'Dic');

Date._NombresDias = new Array('Domingo', 'Lunes', 'Martes', 'Miércoles', 'Jueves', 'Viernes', 'Sábado', 'Domingo');
Date._ANombresDias = new Array('Dom', 'Lun', 'Mar', 'Mié', 'Jue', 'Vie', 'Sáb', 'Dom');

// Constantes utilizadas para los cálculos de tiempo
Date.SECOND = 1000; // milisegundos
Date.MINUTE = 60 * Date.SECOND;
Date.HOUR   = 60 * Date.MINUTE;
Date.DAY    = 24 * Date.HOUR;
Date.WEEK   =  7 * Date.DAY;

Date.parseDate = function(str, fmt) {
	var today = new Date();
	var y = 0;
	var m = -1;
	var d = 0;
	var a = str.split(/\W+/);
	var b = fmt.match(/%./g);
	var i = 0, j = 0;
	var hr = 0;
	var min = 0;
	for (i = 0; i < a.length; ++i) {
		if (!a[i]) continue;
		switch (b[i]) {
		case "%d":
		case "%e":
			d = parseInt(a[i], 10);
			break;

		case "%m":
			m = parseInt(a[i], 10) - 1;
			break;

		case "%Y":
		case "%y":
			y = parseInt(a[i], 10);
			if (y < 100) {
				y+= (y > 29? 1900: 2000);
			}
			break;

		case "%b":
		case "%B":
			for (j = 0; j < 12; ++j) {
				if (Date._NombreMes[j].substr(0, a[i].length).toLowerCase() == a[i].toLowerCase()) {
					m = j;
					break;
				}
			}
			break;

		case "%H":
		case "%I":
		case "%k":
		case "%l":
			hr = parseInt(a[i], 10);
			break;

		case "%P":
		case "%p":
			if (/pm/i.test(a[i]) && hr < 12) {
				hr += 12;
			} else if (/am/i.test(a[i]) && hr >= 12) {
				hr -= 12;
			}
			break;

		case "%M":
			min = parseInt(a[i], 10);
			break;
		}
	}
	if (isNaN(y)) y = today.getFullYear();
	if (isNaN(m)) m = today.getMonth();
	if (isNaN(d)) d = today.getDate();
	if (isNaN(hr)) hr = today.getHours();
	if (isNaN(min)) min = today.getMinutes();
	if (y != 0 && m != -1 && d != 0) {
		return new Date(y, m, d, hr, min, 0);
	}
	y = 0; m = -1; d = 0;
	for (i = 0, len = a.length; i < len; i++) {
		if (a[i].search(/[a-zA-Z]+/) != -1) {
			var t = -1;
			for (j = 0; j < 12; j++) {
				if (Date._NombresMes[j].substr(0, a[i].length).toLowerCase() == a[i].toLowerCase()) {
					t = j;
					break;
				}
			}
			if (t != -1) {
				if (m != -1) {
					d = m + 1;
				}
				m = t;
			}
		} else if ((parseInt(a[i], 10) <= 12)&&(m == -1)) {
			m = a[i] - 1;
		} else if ((parseInt(a[i], 10) > 31)&&(y == 0)) {
			y = parseInt(a[i], 10);
			if (y < 100) {
				y+= (y > 29? 1900: 2000);
			}
		} else if (d == 0) {
			d = a[i];
		}
	}
	if (y == 0) {
		y = today.getFullYear();
	}
	if (m != -1 && d != 0) {
		return new Date(y, m, d, hr, min, 0);
	}
	return today;
}
*/
/*
 * Devuelve la cantidad de días en el mes actual
 */
Object.extend(Date.prototype, {
    /**
     * Este método devuelve el número de días que tiene un mes del año de la fecha. Esta función tiene en cuenta los años bisiestos
     * para establecer la cantidad de días del mes de febrero.
     *
     * @param Integer month     Entero que indica el mes del cual se quiere obtener la cantidad de días. Si NO se indica, el método
     *                          asumirá el mes de la fecha del objeto Date.
     *
     * @return Integer          Este método devuelve un entero indicando la cantidad de días que tiene el mes.
     */
    getMonthDays: function(month) {
        var year = this.getFullYear();
        if (typeof month == "undefined") month = this.getMonth();
        if ((((year%4) == 0)&&(((year%100) != 0)||((year%400) != 0)))&&(month == 1)) return 29; // Es bisiesto
        else return Date._DiasMes[month]; // NOes bisiesto
    },

    /**
     * Este método calcula y devuelve el número de día de la fecha contando desde el 1 de enero del año del objeto.
     *
     * @return Integer          Este método devuelve en número de días trnascurridos desde el 1 de enero del año del objeto.
     */
    getDayOfYear: function() {
        var ahora = new Date(this.getFullYear(), this.getMonth(), this.getDate(), 0, 0, 0);
        var entonces = new Date(this.getFullYear(), 0, 0, 0, 0, 0);
        var tiempo = ahora - entonces;
        return Math.floor(tiempo / Date.DAY);
    },

    /**
     * Esta función devuelve el número de la semana dentro del año, como se define en ISO 8601, que establece como primera semana
     * del año aquella que contiene el primer miércoles del año.
     *
     * @return Integer      Esta función devuelve un entero que indica el número de la semana de la fecha.
     */
    getWeekNumber: function() {
        var d = new Date(this.getFullYear(), this.getMonth(), this.getDate(), 0, 0, 0);
        var DoW = d.getDay();
        d.setDate(d.getDate() - (DoW + 6) % 7 + 3); // El miércoles más cercano
        var ms = d.valueOf(); // GMT
        d.setMonth(0);
        d.setDate(4); // Thu in Week 1
        return Math.round((ms - d.valueOf()) / Date.WEEK) + 1;
    },

    /**
     * Este método compara el objeto fecha con el que se le pasa como argumento y devuelve un número que guarda la misma relación
     * con cero que el objeto con el que se le pasa como argumento.
     *
     * @param Date fecha    Es la fecha con la que será comparada el objeto.
     *
     * @return Integer      Este método devuelve un entro menor que cero si el objeto es menor que la fecha que recibe como
     *                      argumento, mayor que cero si el objeto es mayor que la fecha que se le pasa como arcumento e, igual
     *                      a cero si las dos fechas son iguales.
     */
    compareTo: function(fecha) {
        return (this.getTime() - fecha.getTime());
    },

    equalsTo: function(fecha) {
        return this.compareTo(fecha) == 0;
    },

    /**
     * Este método asigna unicamente la fecha del objeto, conservando la hora si existe.
     */
    setDateOnly: function(date) {
        var tmp = new Date(date);
        this.setDate(1);
        this.setFullYear(tmp.getFullYear());
        this.setMonth(tmp.getMonth());
        this.setDate(tmp.getDate());
    },

    /**
     * Este método formatea la fecha según una cadena proporcionada.
     *
     * @param String str        Esta es la cadena que establece el formato a aplicar en la Sobre la Fecha/Hora. En esta cadena de
     *                          formato, podemos incluir los siguientes carácteres con sus significados:
     *                          <dl>
     *                              <dt>%C</dt><dd>El número del siglo.</dd>
     *
     *                              <dt>%Y</dt><dd>El número del año completo (Con los dígitos del siglo).</dd>
     *                              <dt>%y</dt><dd>Lo dos últimos dígitos del año (Sin los dígitos del siglo).</dd>
     *
     *                              <dt>%b</dt><dd>El nombre del mes abreviado a tres carácteres.</dd>
     *                              <dt>%B</dt><dd>El nombre del mes completo.</dd>
     *                              <dt>%m</dt><dd>El número del mes con dos dígitos (01-12).</dd>
     *                              <dt>%U, %W, %V</dt><dd>El número de la semana en el año.</dd>
     *
     *                              <dt>%j</dt><dd>El número de día en el año (1-366).</dd>
     *                              <dt>%d</dt></dd>El número del día del mes con dos dígitos (01-31).</dd>
     *                              <dt>%e</dt><dd>El número del día del mes (1-31).</dd>
     *                              <dt>%a</dt><dd>El nombre del día de la semana abreviado a tres caracteres.</dd>
     *                              <dt>%A</dt><dd>El nombre del día de la semana completo.</dd>
     *                              <dt>%u</dt><dd>El día de la semana (1-7, 1 = Domingo).</dd>
     *                              <dt>%w</dt><dd>El día de la semana (0-6, 0 = Domingo).</dd>
     *
     *                              <dt>%H</dt><dd>Hora del día en formato 24h (00-23).</dd>
     *                              <dt>%h</dt><dd>Hora del día en formato 24h (0-23).</dd>
     *                              <dt>%I</dt><dd>Hora del día en formato 12h (01-12).</dd>
     *                              <dt>%i</dt><dd>Hora del día en formato 12h (1-12).</dd>
     *                              <dt>%P</dt><dd>Cadena que indica si por la tarde o por la mañana (AM/PM).</dd>
     *                              <dt>%p</dt><dd>Cadena que indica si por la tarde o por la mañana (am/pm).</dd>
     *
     *                              <dt>%M</dt><dd>Minuto de la hora (00-59).</dd>
     *
     *                              <dt>%S</dt><dd>Número de segundos dentro de la hora (00-59).</dd>
     *                              <dt>%s</dt><dd>Número de segundos dentro de la hora (0-59).</dd>
     *
     *                              <dt>%n</dt><dd>Retorno de carro (el carácter '\n').</dd>
     *                              <dt>%t</dt><dd>Un salto de tabulación (el carácter '\t').</dd>
     *                              <dt>%%</dt><dd>El signo de porcentaje (el literal '%').</dd>
     *                          </dl>
     *
     * @return String           Este método devuelve una cadena on la fecha formateada según la cadena de formato.
     */
    format: function (str) {
        var m = this.getMonth();
        var d = this.getDate();
        var y = this.getFullYear();
        var wn = this.getWeekNumber();
        var w = this.getDay();
        var s = {};
        var hr = this.getHours();
        var pm = (hr >= 12);
        var ir = (pm) ? (hr - 12) : hr;
        var dy = this.getDayOfYear();
        if (ir == 0)
            ir = 12;
        var min = this.getMinutes();
        var sec = this.getSeconds();
        s["%a"] = Date._ANombresDias[w]; // abbreviated weekday name [FIXME: I18N]
        s["%A"] = Date._NombresDias[w]; // full weekday name
        s["%b"] = Date._ANombresMes[m]; // abbreviated month name [FIXME: I18N]
        s["%B"] = Date._NombresMes[m]; // full month name
        // FIXME: %c : preferred date and time representation for the current locale
        s["%C"] = 1 + Math.floor(y / 100); // the century number
        s["%d"] = (d < 10) ? ("0" + d) : d; // the day of the month (range 01 to 31)
        s["%e"] = d; // the day of the month (range 1 to 31)
        // FIXME: %D : american date style: %m/%d/%y
        // FIXME: %E, %F, %G, %g, %h (man strftime)
        s["%H"] = (hr < 10) ? ("0" + hr) : hr; // hour, range 00 to 23 (24h format)
        s["%h"] = hr;
        s["%I"] = (ir < 10) ? ("0" + ir) : ir; // hour, range 01 to 12 (12h format)
        s["%i"] = ir;
        s["%j"] = (dy < 100) ? ((dy < 10) ? ("00" + dy) : ("0" + dy)) : dy; // day of the year (range 001 to 366)
        s["%k"] = hr;		// hour, range 0 to 23 (24h format)
        s["%l"] = ir;		// hour, range 1 to 12 (12h format)
        s["%m"] = (m < 9) ? ("0" + (1+m)) : (1+m); // month, range 01 to 12
        s["%M"] = (min < 10) ? ("0" + min) : min; // minute, range 00 to 59
        s["%n"] = "\n";		// a newline character
        s["%p"] = pm ? "PM" : "AM";
        s["%P"] = pm ? "pm" : "am";
        // FIXME: %r : the time in am/pm notation %I:%M:%S %p
        // FIXME: %R : the time in 24-hour notation %H:%M
        s["%s"] = Math.floor(this.getTime() / 1000);
        s["%S"] = (sec < 10) ? ("0" + sec) : sec; // seconds, range 00 to 59
        s["%t"] = "\t";		// a tab character
        // FIXME: %T : the time in 24-hour notation (%H:%M:%S)
        s["%U"] = s["%W"] = s["%V"] = (wn < 10) ? ("0" + wn) : wn;
        s["%u"] = w + 1;	// the day of the week (range 1 to 7, 1 = MON)
        s["%w"] = w;		// the day of the week (range 0 to 6, 0 = SUN)
        // FIXME: %x : preferred date representation for the current locale without the time
        // FIXME: %X : preferred time representation for the current locale without the date
        s["%y"] = ('' + y).substr(2, 2); // year without the century (range 00 to 99)
        s["%Y"] = y;		// year with the century
        s["%%"] = "%";		// a literal '%' character

        var re = /%./g;
    // 	if (!Calendar.is_ie5 && !Calendar.is_khtml)
        if (!Prototype.Browser.IE)
            return str.replace(re, function (par) { return s[par] || par; });

        var a = str.match(re);
        for (var i = 0; i < a.length; i++) {
            var tmp = s[a[i]];
            if (tmp) {
                re = new RegExp(a[i], 'g');
                str = str.replace(re, tmp);
            }
        }

        return str;
    }
});
