Moment: isSameOrAfter da una salida aleatoria al comparar moment () con moment ()

Creado en 21 feb. 2017  ·  4Comentarios  ·  Fuente: moment/moment

Descripción
Entonces, un colega y yo encontramos un error en nuestro código que resultó ser causado por nosotros usando una variable indefinida (básicamente moment(undefined) y luego tratando de comparar eso con una nueva instancia de momento ( moment() ) con el método isSameOrAfter .

Entonces, lo que usamos básicamente fue esto:

let isSame = moment(undefined).isSameOrAfter(moment());

Ejecutar ese código una o dos veces devolverá true , pero no siempre. De vez en cuando devuelve false , supongo que es porque crear dos instancias de momento, una después de la otra, sin tiempo definido, podría crearlas con una diferencia de unos pocos microsegundos.

Aquí hay una prueba que ejecuté tanto en Node v7.1.0 en Windows 10 como en Chrome / 56.0.2924.87 con Moment.js 2.17.1.

const moment = require('moment');

function isSameOrAfter() {
    console.log('isSameOrAfter')
    for (let i = 0; i < 1000; i++) {
        let output = moment().isSameOrAfter(moment());
        if (!output) {
            console.log(output, i);
        }
    }
}

function isSame() {
    console.log('isSame')
    for (let i = 0; i < 1000; i++) {
        let output = moment().isSame(moment());
        if (!output) {
            console.log(output, i);
        }
    }
}

function sameExactVariable() {
    console.log('Another test comparing the same exact variable')
    for (let i = 0; i < 1000; i++) {
        const now = moment();
        let output = now.isSame(now);
        if (!output) {
            console.log(output, i);
        }
    }
}

isSameOrAfter();
isSame();
sameExactVariable();

Las dos primeras funciones registrarán false unas cuantas veces de 1000, y la tercera función no lo hará. Solo registra cuando se encuentra con una excepción.

Medio ambiente:
Mar 21 de febrero de 2017 14:36:06 GMT + 0100 (hora estándar de Europa Occidental)
2017-02-21 14:36:06
-60
Mozilla / 5.0 (Windows NT 10.0; Win64; x64) AppleWebKit / 537.36 (KHTML, como Gecko) Chrome / 56.0.2924.87 Safari / 537.36
2.17.1

Comentario más útil

@imrvshah Primero tenga en cuenta que

...isSameOrAfter(moment().format('MM-DD-YYYY'))

crea un nuevo momento con la hora actual, lo formatea como una cadena y pasa esa cadena a isSameOrAfter() , que la analiza nuevamente. Deberías haber dicho:

...isSameOrAfter(moment())

Y salvó el momento -> cadena -> momento de trabajo. Ese es un código mucho mejor, pero también apuesto a que corrige el error. ¿Ha notado advertencias de desaprobación que dicen "oye, se supone que no debes pasar cadenas a momentos como ese"? Moment sabe cómo analizar cadenas ISO 8601 como moment("1982-05-25") . También sabe cómo analizar cadenas donde se especifica el formato, como moment("05-25-1982", "MM-DD-YYYY") . Pero no tiene idea de que una cadena como "05-25-1982" debe ser "MM-DD-YYYY" sin que usted se lo diga. Por lo tanto, permite que el navegador adivine simplemente entregando esa cadena al constructor Date . En otras palabras, su código se desenvuelve así:

m.isSameOrAfter("05-25-1982");
m.isSameOrAfter(moment("05-25-1982"))
m.isSameOrAfter(moment(new Date("05-25-1982")))

Hay una razón por la que desaprobamos eso: da resultados inconsistentes según el navegador que lo esté ejecutando. Entonces, con lo que se está encontrando es que iOS no es compatible con ese formato de forma nativa. En mi consola de desarrollo de Safari:

> new Date("05-25-1982")
Invalid Date

Eso te dio malas comparaciones que te dejaron con una matriz vacía.

Todos 4 comentarios

Probablemente tengo el mismo tipo de problema. Funciona como se esperaba en dispositivos Chrome y Android, pero no en iOS.

let arrDates: Array<String> = []; _.each(Dates, (date) => { if (moment(date).isSameOrAfter(moment().format('MM-DD-YYYY'))) { arrDates.push(date); } });

en iOS obtengo una matriz nula mientras funciona en Chrome y Android.

Medio ambiente:

CLI de Córdoba: 6.4.0
Versión del marco iónico: 2.0.0
Versión Ionic CLI: 2.1.18
Versión Ionic App Lib: 2.1.9
Versión de scripts de la aplicación iónica: 1.0.0
ios-deploy versión: 1.9.0
versión ios-sim: 5.0.13
SO: macOS Sierra
Versión de nodo: v6.9.2
Versión de Xcode: Xcode 8.2.1 Versión de compilación 8C1002

@ErikMartensson

Supongo que se debe a que crear dos instancias de momento, una tras otra, sin tiempo definido, podría crearlas con una diferencia de unos pocos microsegundos.

Sí, moment() o moment(undefined) son idénticos, significa ahora . Las fechas de JS tienen una resolución de milisegundos, por lo que si ahora es un milisegundo diferente, lo que a veces sucederá, una vez es tras otra. AFAIK, JS no define qué orden moment().isSameOrAfter(moment()) evalúa esas dos llamadas moment() . Pero dado que obviamente tiene que hacer la segunda llamada antes de ejecutar isSameOrAfter() todos modos, no me sorprendería si la segunda en la práctica siempre viene primero. Eso significaría que si hay una diferencia de tiempo, también fallará la parte "oDespués" de la prueba. Puede confirmar esto con un depurador.

No se que decirte. Así es como tienen que funcionar las fechas y horas de resolución finita; "ahora" significa un momento diferente según el momento en que lo diga.

@imrvshah Primero tenga en cuenta que

...isSameOrAfter(moment().format('MM-DD-YYYY'))

crea un nuevo momento con la hora actual, lo formatea como una cadena y pasa esa cadena a isSameOrAfter() , que la analiza nuevamente. Deberías haber dicho:

...isSameOrAfter(moment())

Y salvó el momento -> cadena -> momento de trabajo. Ese es un código mucho mejor, pero también apuesto a que corrige el error. ¿Ha notado advertencias de desaprobación que dicen "oye, se supone que no debes pasar cadenas a momentos como ese"? Moment sabe cómo analizar cadenas ISO 8601 como moment("1982-05-25") . También sabe cómo analizar cadenas donde se especifica el formato, como moment("05-25-1982", "MM-DD-YYYY") . Pero no tiene idea de que una cadena como "05-25-1982" debe ser "MM-DD-YYYY" sin que usted se lo diga. Por lo tanto, permite que el navegador adivine simplemente entregando esa cadena al constructor Date . En otras palabras, su código se desenvuelve así:

m.isSameOrAfter("05-25-1982");
m.isSameOrAfter(moment("05-25-1982"))
m.isSameOrAfter(moment(new Date("05-25-1982")))

Hay una razón por la que desaprobamos eso: da resultados inconsistentes según el navegador que lo esté ejecutando. Entonces, con lo que se está encontrando es que iOS no es compatible con ese formato de forma nativa. En mi consola de desarrollo de Safari:

> new Date("05-25-1982")
Invalid Date

Eso te dio malas comparaciones que te dejaron con una matriz vacía.

@icambron

Estoy de acuerdo con usted y descubro el caso en una consola: era una advertencia de obsolescencia debido al formato de fecha.

Gracias por tu comentario sobre no envolverlo varias veces y usarlo. ...isSameOrAfter(moment())

¿Fue útil esta página
0 / 5 - 0 calificaciones