Moment: Admite duraciones no válidas

Creado en 28 jul. 2014  ·  44Comentarios  ·  Fuente: moment/moment

Actualmente no hay forma de determinar si un análisis de duración fue exitoso, incluso inspeccionando los campos.

New Feature

Comentario más útil

¿Hay alguna actualización sobre esto?

Con moment 2.23.0 la función isValid() también devuelve true al intentar crear una duración a partir de una cadena ISO8601 no válida.

Ejemplo:

const mom = moment.duration('asdf')
console.log(mom.isValid()) // This returns true, expected would be false 

Es un poco molesto en mi opinión. y frustra por completo el propósito de la función isValid() en Duration objetos (¿hay siquiera un caso, cuando isValid() devuelve false ya que el momento interpreta incluso una ¿aporte?)

Todos 44 comentarios

Estoy de acuerdo. Necesitamos un método isValid para empezar.

Creo que las duraciones no válidas deberían generar excepciones y el manejo actual de duraciones no válidas es un error, no una mejora. Considere estos casos:

`var wrong = moment.duration(3,'mintues');`

Cual sera el resultado? Los documentos no definen qué sucede con una entrada incorrecta.

Esto tiene un efecto en cascada, ya que se usa duration lugar de add() y subtract() , por lo que estos también tienen un comportamiento indefinido:

var hmm = moment().subtract(3,'mintues').toDate();
var uhoh = moment().add(3,'mintues').toDate();

De la prueba manual puedo decirle lo que sucede: moment "tiene éxito" usando una duración de cero.

Si moment() simplemente hubiera lanzado una excepción por una entrada incorrecta, este problema se habría identificado de inmediato. Dado que "tuvo éxito" silenciosamente, persistió un error de clase Garbage-In, Garbage-Out.

Dado que el comportamiento de la duración con errores tipográficos no está definido actualmente, comenzar a lanzar excepciones en cadenas incorrectas sería compatible con versiones anteriores.

Si se usa una cadena que no es confiable y que puede tener un error tipográfico, try/catch se puede usar explícitamente al probar si la cadena se puede usar para describir una duración válida.

+1 @markstos.

¿Qué hay de admitir una opción strict (como el momento mismo para las fechas) que arroja? Devolver una duración de cero cuando el análisis falla es bastante peligroso.

Una opción strict sería mejor que ningún cambio, pero no creo que analizar las fechas no válidas como duración cero sea un buen comportamiento predeterminado en primer lugar.

Acordado. ¿Un posible cambio solo aterrizaría con [email protected]?

¿Por qué no usar el mismo patrón que el resto del momento? Tenga un campo _isValid y un método isValid () y establezca una duración como no válida si falla el análisis.

Como referencia, aquí están los otros lugares documentados donde se usa isValid ():

https://github.com/moment/momentjs.com/search?utf8=%E2%9C%93&q=isValid

La vinculación a la documentación, no al código, fue intencional, aunque las menciones del código también son relevantes.

+1
Es muy necesaria la capacidad de averiguar si el análisis se ha realizado correctamente o no.
Si la compatibilidad con versiones anteriores es una preocupación, entonces podría ser posible introducir un método Duration.parse(input: string, strict?: boolean = true): Duration que arrojaría si la entrada es incorrecta y se especifica el argumento strict .
El comportamiento actual cuando obtenemos una Duración con todos ceros para datos arbitrarios es muy extraño.

+1
Tener un método isValid () en una duración (para ver si el análisis fue exitoso) sería útil

Hola a todos, Moment 2.18.0 ahora tiene un método .isValid para duraciones. Sin embargo, es bastante indulgente. @markstos @theazureshadow y otros, avísanos si tienes sugerencias.

@marwahaha ,

Como prueba inicial, copié / pegué uno de los ejemplos anteriores. En lugar de devolver verdadero o falso como se esperaba, lanza una excepción (con el momento 2.18.0):

 moment.duration(3,'mintues').isValid();

(Creada la duración inválida todavía "tiene éxito" sin lanzar una excepción, pero ahora verificando para ver si es válida arroja una excepción!)

Aunque parece que todavía no hay documentos para el nuevo método, quizás este no sea el uso previsto.

@markstos Acabo de ejecutar ese código en la consola de Momentjs.com, que tiene 2.18.0, sin ningún problema. ¿Podemos obtener más detalles sobre eso?

Quizás, ese código debería ser inválido porque los minutos están mal escritos.

El 21 de marzo de 2017 a las 2:35 p.m., "Maggie Pint" [email protected] escribió:

@markstos https://github.com/markstos Acabo de ejecutar ese código en el
consola de Momentjs.com, que tiene 2.18.0, sin problemas. Podemos obtener
más detalles sobre eso?

-
Recibes esto porque te mencionaron.
Responda a este correo electrónico directamente, véalo en GitHub
https://github.com/moment/moment/issues/1805#issuecomment-288176838 , o silenciar
la amenaza
https://github.com/notifications/unsubscribe-auth/ACbGmWIf24KlRs8oiS2wTn206iJNMod7ks5roBhfgaJpZM4CRuVM
.

@maggiepint @marwahaha Sí, la falta de ortografía de "minutos" ES la razón por la que la duración no debería ser válida.

@markstos Tampoco puedo reproducir esa excepción en la consola de Momentjs.com. (Eso es 2.18.1 ahora, sin embargo). Si aún puede reproducir la excepción al llamar a isValid, ¿podemos obtener más detalles?

screen shot 2017-03-22 at 10 38 06

(Obviamente, Mark quería que isValid devolviera false en esta situación, pero ese es un problema separado de la excepción. No es 100% obvio para mí cómo debemos manejar la validez del análisis con entradas de objetos).

Tampoco puedo reproducir la excepción con 2.18.1. Quizás fue una falsa alarma. Puedo reproducir resultado @butterflyhug 's de tener este tipo de duración no válida regresar 'verdadero' para 'isValid ()'.

¿No debería fallar el análisis en este caso en lugar de devolver "0 minutos" como una salida erróneamente válida como resultado?

Debería es una pregunta diferente, pero el IIRC lo que hace es interpretar que
valor en milisegundos porque la unidad no se encuentra en la tabla hash de unidades.

¿Debería ser inválido? En mi opinión probablemente.

El 22 de marzo de 2017 a las 8:42 a. M., "Mark Stosberg" [email protected] escribió:

Tampoco puedo reproducir la excepción con 2.18.1. Quizás fue un falso
alarma. Puedo reproducir @butterflyhug https://github.com/butterflyhug 's
resultado de que este tipo de duración no válida devuelva "verdadero" para
"es válida()".

¿No debería fallar el análisis en este caso en lugar de devolver "0 minutos" como un
salida erróneamente válida como resultado?

-
Recibes esto porque te mencionaron.
Responda a este correo electrónico directamente, véalo en GitHub
https://github.com/moment/moment/issues/1805#issuecomment-288440827 , o silenciar
la amenaza
https://github.com/notifications/unsubscribe-auth/AFxi0nZAz8gwAJM8fVx5rYPyIWjeEfHMks5roUF4gaJpZM4CRuVM
.

Parece haber un error aquí:

https://github.com/moment/moment/blob/497f918515ae6ab900f008f19523b1e4ae5e2450/src/lib/duration/create.js#L34

Se asume que allí la cadena es válida y aparece en el mapa de "duración". Parece que la solución es agregar una marca aquí para confirmar que la cadena es un valor válido para establecer. Si no es así, establezca _isValid:false

Este comportamiento es consistente con el método estándar isValid :

moment({'mintues': 3}).isValid()
> true

La fuente de esto es normalizeObjectUnits https://github.com/moment/moment/blob/497f918515ae6ab900f008f19523b1e4ae5e2450/src/lib/units/aliases.js#L14 -L29 que solo agrega atributos válidos (y elimina los unos).

@maggiepint @ichernev ¿ debería cambiar este comportamiento? Pronto haremos un lanzamiento de última hora ...

Convertir '3 minutos' a '0 minutos' y declarar el resultado "válido" es un error. Puede ser un cambio importante arreglarlo, pero sigue siendo una corrección de errores.

Estoy de acuerdo en que este comportamiento de validación no es ideal, pero no estoy de acuerdo en que esto sea necesariamente un error .

Considere el caso en el que analiza algo como moment({'minutes': 3, '$cacheKey': 92619502}).isValid() . Espero encarecidamente que tengamos usuarios que aprecien tener ese análisis como un momento válido, y no veo una distinción de principios entre este ejemplo y el error que escribió.

La API que estamos discutiendo es un "analizador de objetos" para el constructor moment , que se documenta aquí:

http://momentjs.com/docs/#/parsing/object/

Actualmente, la documentación no dice nada sobre el tratamiento de pasar argumentos desconocidos o adicionales.

En este momento, el comportamiento de Moment aquí se puede describir como "Entrada de basura, salida de basura". La entrada de basura se acepta silenciosamente y el resultado es "Basura fuera" - ¡las fechas mal escritas se convierten a otras fechas y se consideran válidas!

Estas actualizaciones permitirían a un desarrollador descubrir lo antes posible que ha cometido un error:

  • El documento de que se lanzará una excepción en argumentos desconocidos se pasa al constructor del objeto.

    • Lanzar una excepción si se pasan argumentos desconocidos al constructor del objeto

Mientras Moment continúe aceptando "Garbage In" como válido, seguirá siendo un flaco favor para los desarrolladores y los usuarios se quedarán con Moment informando erróneamente que las fechas rotas son "válidas".

Esta mejora parece bien merecer un cambio "rotundo".

Me acaba de morder esto: moment().subtract('1 day') ... esta no es una forma válida de expresar una duración. Sin embargo, no esperaría que fuera equivalente a .subtract(0) . En mi opinión, lo menos sorprendente que se puede hacer en este caso es lanzar.

@johnvh Estoy completamente de acuerdo.

¿Sabes que no es una "forma válida de expresar una duración", pero escribes ese código de todos modos? ¿Qué esperas? Supongo que resolvió que no era una forma válida de expresar una duración a partir de la excelente documentación que brindan los autores.

El 25/04/2017, a las 08:29, Mark Stosberg [email protected] escribió:

@johnvh Estoy completamente de acuerdo.

-
Estás recibiendo esto porque estás suscrito a este hilo.
Responda a este correo electrónico directamente, véalo en GitHub o silencie el hilo.

Los desarrolladores de @johnvh hubiera recibido inmediatamente una falla de validación cuando se ejecutó su código, podría haber revisado la excelente documentación para ver cuál podría ser el problema. Desafortunadamente, Moment trató la entrada inválida como válida y no emitió ninguna alarma.

@markstos exactamente. Estoy 100% de acuerdo.

Este fue un error que tuvo que ser rastreado. No lo escribimos de esa manera sabiendo que no era válido, por supuesto. Parece correcto, ya que los métodos de manipulación del momento son muy liberales en sus firmas compatibles. También usamos agenda en el mismo proyecto, que usa intervalo humano para convertir el lenguaje natural en duraciones. Así que tendremos algo como esto solo con líneas separadas:

moment().subtract('1 day');
agenda.processEvery('1 day');

El último funciona según lo previsto, el primero no. Si el primero planteara una excepción, nos habría alertado de nuestro error.

Además, el hecho de que Moment / tiene / un método isValid () implica que valida los valores como válidos o no válidos. En los casos en que los valores no válidos se clasifican como válidos, el método isValid() parece no funcionar como se documenta.

Hola a todos, ¡nos encantaría revisar cualquier RP en esta área!

Me encontré con este error o algo similar. Si ejecuto moment.duration('3', 'minutes').asMinutes() usando el Momento 2.18.1, obtengo un resultado de 0. Creo que debería devolver 3 o lanzar una excepción. Como mínimo, moment.duration('3', 'minutes').isValid() debería devolver false .

La forma en que Moment se comporta ahora puede causar muchos problemas al causar errores que pueden ser difíciles de detectar y diagnosticar, como varias personas aquí han mencionado.

¿Se ha abordado esto?

@TomJSmith Una prueba rápida muestra que el error aún existe. Este código:

 moment().subtract('1 day');

"tiene éxito", restando cero días en lugar de un día como se esperaba. Puede llamar a .isValid() en la fecha resultante y obtener una respuesta true indicando que el resultado es válido cuando no lo es.

El comportamiento actual podría tener malas consecuencias en algunos casos de uso y debe documentarse claramente con una advertencia:

Caso de uso
Quiero eliminar recursos según la duración de la retención:

const duration = moment.duration('invalid');
const currentDate = moment();
const removeBeforeDate  = moment().subtract(duration);

console.log(`currentDate      : ${currentDate}`);
console.log(`removeBeforeDate : ${removeBeforeDate}`);

Resultado:

currentDate      : Fri Apr 13 2018 13:15:04 GMT+0200
removeBeforeDate : Fri Apr 13 2018 13:15:04 GMT+0200

Consecuencia:
Todos los recursos hasta la fecha actual se eliminan ...

Hasta ahora, la única forma que encontré para solucionar esto es probar el valor después del análisis:

const duration = moment.duration('invalid');
if (duration.toISOString() === 'P0D') {
    // throw an Error
}

Sí, este error es malo y ha estado abierto desde 2014. Esto es algo que los proyectos "date-fns" hacen bien. De hecho, le dicen si la entrada inválida no es válida. https://date-fns.org/ Desafortunadamente, date-fns no maneja las conversiones de zona horaria, pero quizás haya una manera de manejarlas con una biblioteca externa.

Para que el proyecto Moment solucione esto, deben dejar de aceptar la entrada de basura y tratarla como una fecha válida. Si bien esto parece un mejor comportamiento, técnicamente es un cambio de "comportamiento de ruptura al revés", por lo que parece que hay resistencia para hacer el cambio. Pero dado que el proyecto no ha tomado medidas en los últimos casi cuatro años, no esperaría una solución pronto.

¿Hay alguna actualización sobre esto?

Con moment 2.23.0 la función isValid() también devuelve true al intentar crear una duración a partir de una cadena ISO8601 no válida.

Ejemplo:

const mom = moment.duration('asdf')
console.log(mom.isValid()) // This returns true, expected would be false 

Es un poco molesto en mi opinión. y frustra por completo el propósito de la función isValid() en Duration objetos (¿hay siquiera un caso, cuando isValid() devuelve false ya que el momento interpreta incluso una ¿aporte?)

@robbiecloset La actualización es desde mi última publicación en abril, el proyecto "date-fns" ha mejorado en el soporte de la zona horaria. Ahora hay proyectos "date-fns-timezone" y "date-fns-tz" para ayudar con esto.

Consideraría usarlo si es posible cambiarlo.

Yo uso moment.duration(value).toISOString() === value , ese valor se lee de una configuración.

Yo uso moment.duration (value) .toISOString () === value, ese valor se lee de una configuración.

@ bors-ltd Creo que parte del problema es que el momento podría decodificar dos valores que producen el mismo valor codificado.

Por ejemplo: moment.duration('PT0M0S').toISOString() === moment.duration('PT0S').toISOString() .

Si observa las pruebas, parece que los valores no válidos son en realidad parte de la especificación:

https://github.com/moment/moment/blob/2.24.0/src/test/moment/duration.js#L419 -L420

Los patrones que no coinciden con el estándar de duración ISO se prueban como "0" segundos.

Hola, también tuvimos el mismo problema con el método isValid() y terminamos haciéndolo manualmente.
const isValidDuration = duration => { return !!duration.match( /^(-?)P(?=\d|T\d)(?:(\d+)Y)?(?:(\d+)M)?(?:(\d+)([DW]))?(?:T(?:(\d+)H)?(?:(\d+)M)?(?:(\d+(?:\.\d+)?)S)?)?$/ ); };
Espero que pueda ayudar a cualquiera.

Ver https://momentjs.com/docs/#/ -project-status /

Gracias por toda la discusión aquí.

Una solución hacky es reemplazar el método isValid con un método que asegure que la suma de las partes de datos es> 0 (o al menos probablemente inválida)

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