El constructor de fechas devuelve NaN en IE, pero funciona en Firefox y Chrome

79

Estoy intentando crear un pequeño calendario en JavaScript. Tengo mis fechas funcionando muy bien en Firefox y Chrome, pero en IE las funciones de fecha están devolviendo NaN.

Aquí está la función:

function buildWeek(dateText){
    var headerDates='';
    var newDate = new Date(dateText);

    for(var d=0;d<7;d++){
        headerDates += '<th>' + newDate + '</th>';
        newDate.setDate(newDate.getDate()+1);
    }                       

    jQuery('div#headerDates').html('<table><tr>'+headerDates+'</tr></table>');
}

dateTextes el lunes de la semana actual que en realidad está configurado en php con el formato 'm, d, Y', por ejemplo "02, 01, 2010".

pedalear
fuente
2
Tiene algunos errores de copiar y pegar en su muestra de código, mire la declaración for: for(var d=0;d';eso generará un SyntaxError...
Christian C. Salvadó
¿Responde esto a tu pregunta? ¿Por qué Date.parse da resultados incorrectos?
Heretic Monkey

Respuestas:

67

El constructor Date acepta cualquier valor. Si el [[valor]] primitivo del argumento es número, entonces la Fecha que se crea tiene ese valor. Si el primitivo [[valor]] es String, entonces la especificación solo garantiza que el constructor Date y el método parse son capaces de analizar el resultado de Date.prototype.toString y Date.prototype.toUTCString ()

Una forma confiable de establecer una fecha es construir una y usar los métodos setFullYeary setTime.

Un ejemplo de eso aparece aquí: http://jibbering.com/faq/#parseDate

ECMA-262 r3 no define ningún formato de fecha. Pasar valores de cadena al constructor Date o Date.parse tiene un resultado dependiente de la implementación. Es mejor evitarlo.


Editar: La entrada de las preguntas frecuentes de comp.lang.javascript es: Un formato de fecha local ISO 8601 extendido YYYY-MM-DDse puede analizar Datecon lo siguiente: -

/**Parses string formatted as YYYY-MM-DD to a Date object.
 * If the supplied string does not match the format, an 
 * invalid Date (value NaN) is returned.
 * @param {string} dateStringInRange format YYYY-MM-DD, with year in
 * range of 0000-9999, inclusive.
 * @return {Date} Date object representing the string.
 */

  function parseISO8601(dateStringInRange) {
    var isoExp = /^\s*(\d{4})-(\d\d)-(\d\d)\s*$/,
        date = new Date(NaN), month,
        parts = isoExp.exec(dateStringInRange);

    if(parts) {
      month = +parts[2];
      date.setFullYear(parts[1], month - 1, parts[3]);
      if(month != date.getMonth() + 1) {
        date.setTime(NaN);
      }
    }
    return date;
  }
Garrett
fuente
Gracias Garrett. Esa función que proporcionaste en el enlace es la mejor, mucho más concisa que cualquier otra cosa que haya podido encontrar, ¡y funciona con el formato de fecha que utilizo en el otro 99% de la aplicación! Mucho más consistente de lo que estaba usando.
pedalpete
Esto, lamentablemente, no es bueno, ya que muchos formatos estructurados solo usan formatos de fecha / hora W3C (ISO-8601 con especificaciones completas más o menos). Entonces, si bien las marcas de tiempo son mejores en muchos aspectos (más simples, más eficientes, funcionan con todos los navegadores), a menudo se requiere que los datos estándar de fecha / hora sean analizadores de javascript. Me pregunto si jQuery o similares tendrían mejores métodos de análisis.
StaxMan
3
gracias por señalar, volviéndose loco por qué Chrome funciona bien al analizar las fechas mientras ie7 dice NAN, lo bueno es que $ .datepicker.parseDate de jquery puede analizar las fechas
Carlos Jaime C. De Leon
¿Y si también quieres milisegundos?
okysabeni
He estado usando una función que se derivó de este código para analizar una fecha / hora ISO de una cadena. En raras ocasiones tendré un valor aparentemente válido que ingrese en la if (month != date.getMonth() + 1)declaración, invalidando la fecha. Por ejemplo 2014-06-01T01:09:22.68,. ¿Puede explicar el propósito de esta ifdeclaración?
Grinn
87

Desde un formato mysql datetime / timestamp:

var dateStr="2011-08-03 09:15:11"; //returned from mysql timestamp/datetime field
var a=dateStr.split(" ");
var d=a[0].split("-");
var t=a[1].split(":");
var date = new Date(d[0],(d[1]-1),d[2],t[0],t[1],t[2]);

Espero que sea de utilidad para alguien. Funciona en IE FF Chrome

Qlimax
fuente
Funciona con todos los navegadores. Thnx
Tejas
1
const a = dateStr.split(' '); const d = a[0].split('-'); const t = a[1].split(':'); currentValue.created_date = new Date(+d[0], (+d[1] - 1), +d[2], +t[0], +t[1]);para ES5 o mejor.
Sydwell
15

No use "nueva fecha ()", porque toma la cadena de fecha de entrada como hora local:

new Date('11/08/2010').getTime()-new Date('11/07/2010').getTime();  //90000000
new Date('11/07/2010').getTime()-new Date('11/06/2010').getTime();  //86400000

debemos usar "NewDate ()", toma la entrada como hora GMT:

function NewDate(str)
         {str=str.split('-');
          var date=new Date();
          date.setUTCFullYear(str[0], str[1]-1, str[2]);
          date.setUTCHours(0, 0, 0, 0);
          return date;
         }
NewDate('2010-11-07').toGMTString();
NewDate('2010-11-08').toGMTString();
diyismo
fuente
7

Aquí hay otro enfoque que agrega un método al Dateobjeto

uso: var d = (new Date()).parseISO8601("1971-12-15");

    / **
     * Analiza la fecha con formato ISO 8601 en un objeto de fecha, ISO 8601 es AAAA-MM-DD
     * 
     * @param {String} fecha la fecha como una cadena, por ejemplo, 1971-12-15
     * @returns {Date} Objeto de fecha que representa la fecha de la cadena proporcionada
     * /
    Date.prototype.parseISO8601 = function (date) {
        var coincide con fecha.match (/ ^ \ s * (\ d {4}) - (\ d {2}) - (\ d {2}) \ s * $ /);

        si (coincide) {
            this.setFullYear (parseInt (coincide con [1]));    
            this.setMonth (parseInt (coincide con [2]) - 1);    
            this.setDate (parseInt (coincide con [3]));    
        }

        devuelve esto;
    };
magikMaker
fuente
2

Siempre guardo mi fecha en hora UTC.

Esta es mi propia función hecha de las diferentes funciones que encontré en esta página.

Toma un STRING como formato mysql DATETIME (ejemplo: 2013-06-15 15:21:41). La verificación con la expresión regular es opcional. Puede eliminar esta parte para mejorar el rendimiento.

Esta función devuelve una marca de tiempo.

El DATETIME se considera una fecha UTC . Tenga cuidado: si espera una fecha y hora local, esta función no es para usted.

    function datetimeToTimestamp(datetime)
    {
        var regDatetime = /^[0-9]{4}-(?:[0]?[0-9]{1}|10|11|12)-(?:[012]?[0-9]{1}|30|31)(?: (?:[01]?[0-9]{1}|20|21|22|23)(?::[0-5]?[0-9]{1})?(?::[0-5]?[0-9]{1})?)?$/;
        if(regDatetime.test(datetime) === false)
            throw("Wrong format for the param. `Y-m-d H:i:s` expected.");

        var a=datetime.split(" ");
        var d=a[0].split("-");
        var t=a[1].split(":");

        var date = new Date();
        date.setUTCFullYear(d[0],(d[1]-1),d[2]);
        date.setUTCHours(t[0],t[1],t[2], 0);

        return date.getTime();
    }
Gabriel
fuente
2

Aquí hay un fragmento de código que corrige ese comportamiento de IE (v ['fecha'] es una cadena de fecha separada por comas, por ejemplo, "2010,4,1"):

if($.browser.msie){
    $.lst = v['date'].split(',');
    $.tmp = new Date(parseInt($.lst[0]),parseInt($.lst[1])-1,parseInt($.lst[2]));
} else {
    $.tmp = new Date(v['date']);
}

El enfoque anterior no consideró que el mes de JS Date se basa en CERO ...

Perdón por no explicar demasiado, estoy en el trabajo y pensé que esto podría ayudar.

Martin Zeitler
fuente
1

Este es mi enfoque:

var parseDate = function(dateArg) {
    var dateValues = dateArg.split('-');
    var date = new Date(dateValues[0],dateValues[1],dateValues[2]);
    return date.format("m/d/Y");
}

reemplácelo ('-')con el delimitador que está usando.

xin
fuente
1

Envíe el texto de la fecha y el formato en el que está enviando el texto de la fecha en el método siguiente. Analizará y devolverá como fecha y esto es independiente del navegador.

function cal_parse_internal(val, format) {
val = val + "";
format = format + "";
var i_val = 0;
var i_format = 0;
var x, y;
var now = new Date(dbSysCurrentDate);
var year = now.getYear();
var month = now.getMonth() + 1;
var date = now.getDate();

while (i_format < format.length) {
    // Get next token from format string
    var c = format.charAt(i_format);
    var token = "";
    while ((format.charAt(i_format) == c) && (i_format < format.length)) {
        token += format.charAt(i_format++);
    }
    // Extract contents of value based on format token
    if (token == "yyyy" || token == "yy" || token == "y") {
        if (token == "yyyy") { x = 4; y = 4; }
        if (token == "yy")   { x = 2; y = 2; }
        if (token == "y")    { x = 2; y = 4; }
        year = _getInt(val, i_val, x, y);
        if (year == null) { return 0; }
        i_val += year.length;
        if (year.length == 2) {
            if (year > 70) {
                year = 1900 + (year - 0);
            } else {
                year = 2000 + (year - 0);
            }
        }
    } else if (token == "MMMM") {
        month = 0;
        for (var i = 0; i < MONTHS_LONG.length; i++) {
            var month_name = MONTHS_LONG[i];
            if (val.substring(i_val, i_val + month_name.length) == month_name) {
                month = i + 1;
                i_val += month_name.length;
                break;
            }
        }
        if (month < 1 || month > 12) { return 0; }
    } else if (token == "MMM") {
        month = 0;
        for (var i = 0; i < MONTHS_SHORT.length; i++) {
            var month_name = MONTHS_SHORT[i];
            if (val.substring(i_val, i_val + month_name.length) == month_name) {
                month = i + 1;
                i_val += month_name.length;
                break;
            }
        }
        if (month < 1 || month > 12) { return 0; }
    } else if (token == "MM" || token == "M") {     
        month = _getInt(val, i_val, token.length, 2);
        if (month == null || month < 1 || month > 12) { return 0; }
        i_val += month.length;
    } else if (token == "dd" || token == "d") {
        date = _getInt(val, i_val, token.length, 2);
        if (date == null || date < 1 || date > 31) { return 0; }
        i_val += date.length;
    } else {
        if (val.substring(i_val, i_val+token.length) != token) {return 0;}
        else {i_val += token.length;}
    }
}

// If there are any trailing characters left in the value, it doesn't match
if (i_val != val.length) { return 0; }

// Is date valid for month?
if (month == 2) {
    // Check for leap year
    if ((year%4 == 0 && year%100 != 0) || (year%400 == 0)) { // leap year
        if (date > 29) { return false; }
    } else {
        if (date > 28) { return false; }
    }
}
if (month == 4 || month == 6 || month == 9 || month == 11) {
    if (date > 30) { return false; }
}
return new Date(year, month - 1, date);
}
Valli
fuente
Gracias Valli. Seguí la respuesta de Garrett a continuación, ya que la función a la que se vinculó era más pequeña y trabajé con el formato de fecha que uso regularmente.
pedalpete
0

El constructor de fecha en JavaScript necesita una cadena en uno de los formatos de fecha admitidos por el método parse ().

Aparentemente, el formato que está especificando no es compatible con IE, por lo que deberá cambiar el código PHP o analizar la cadena manualmente en JavaScript.

richardtallent
fuente
4
Eso es bastante obvio, pero sería bueno saber qué formatos compatibles podrían ser ...
StaxMan
0

Puede utilizar el siguiente código para analizar la cadena de fecha ISO8601:

function parseISO8601(d) {
    var timestamp = d;
    if (typeof (d) !== 'number') {
        timestamp = Date.parse(d);
    }
    return new Date(timestamp);
};
isaranchuk
fuente
0

Pruebe utilizando la getDatefunción de datepicker.

$.datepicker.formatDate('yy-mm-dd',new Date(pField.datepicker("getDate")));
Devika Anup
fuente
0

Probé toda la solución anterior pero nada funcionó para mí. Hice una lluvia de ideas y encontré esto y también funcioné bien en IE11.

value="2020-08-10 05:22:44.0";
var date=new Date(value.replace(" ","T")).$format("d/m/yy h:i:s");
console.log(date);

si $ format no funciona para usted, use format solamente.

PRAFUL KUMAR
fuente