El peligroso analizador de fechas en JavaScript: cómo evitar errores comunes
El constructor new Date(string) en JavaScript intenta extraer una fecha de cualquier entrada de texto, a menudo generando resultados inesperados. Esto no es un error, sino una característica de los motores V8 y SpiderMonkey, donde el analizador interpreta el texto de forma agresiva.
Ejemplos que ilustran el problema:
new Date("2020-01-23")
// Mié 22 ene 2020 19:00:00 GMT-0500 (interpretado como UTC)
new Date("Hoy es 2020-01-23")
// Jue 23 ene 2020 00:00:00 GMT-0500 (hora local)
new Date("Ruta 66")
// Sáb 1 ene 1966 00:00:00 GMT-0500
new Date("Beverly Hills, 90210")
// Lun 1 ene 90210 00:00:00 GMT-0500
Estas conversiones generan objetos Date válidos con valores incorrectos, lo que complica el proceso de depuración. El caso "Catch 22" devuelve Fecha inválida, algo raro pero técnicamente correcto.
Cómo funciona el analizador de V8
La especificación de ECMAScript exige parsear solo una subconjunto del estándar ISO 8601. Todo lo demás depende de la implementación.
Algoritmo de V8:
- Verifica si hay formato ISO 8601: la cadena debe comenzar con un año de cuatro dígitos o un signo.
- Si no, recurre al analizador heredado: ignora palabras hasta encontrar el primer número.
- Procesa los números en
DayComposer:
- 1–12: interpretados como mes.
- 13–31: ambiguos, a menudo rechazados.
- 32+: tratados como año (50–99 +1900).
- Por defecto: 1 de enero.
Esto explica por qué "Ruta 66" se convierte en 1966 y "90210" en el año 90210.
Confusión con husos horarios
Las cadenas ISO como "2020-01-23" se parsean como UTC, mientras que los formatos antiguos usan la hora local. La diferencia surge de los prefijos:
- ISO puro: parseado como UTC.
- Cadenas con texto: modo heredado, hora local.
Espacios al inicio o final alteran el comportamiento del analizador, desplazando los resultados hasta un día completo según el huso horario.
Safari (JavaScriptCore) es más estricto: rechaza ejemplos heredados y cadenas con espacios al final.
Errores reales y soluciones
En proyectos reales, usar new Date() como respaldo para entradas de usuario puede convertir "Ruta 66" en una fecha, corruptando tablas de datos. Solución: confiar únicamente en analizadores personalizados con validación por expresiones regulares.
Prácticas recomendadas para desarrolladores intermedios y senior:
- Valida el formato con regex antes de llamar a
new Date(). - Usa
date-fns parseISO()para parseo estricto de ISO. - Para control total, emplea bibliotecas como Luxon o Day.js con analizadores personalizados.
- Nunca uses
new Date(string)con entradas no confiables. - Prueba en múltiples navegadores: V8, SpiderMonkey, JSC.
JavaScript vs Python: Una comparación
Python evita ambigüedades:
datetime.fromisoformat(): acepta solo ISO 8601.strptime(): formato estricto, sin caracteres adicionales permitidos.
El analizador heredado de JavaScript adivina silenciosamente; Python lanza un ValueError.
Conclusiones clave
- El analizador de
Datecrea objetos válidos pero incorrectos a partir de texto aleatorio. - El comportamiento del analizador (ISO vs heredado) depende de prefijos y espacios.
- En producción: valida siempre la entrada antes de parsear.
- Migrar al API Temporal para código futuro-proof.
- La prueba entre navegadores es esencial debido a diferencias en motores.
— Editorial Team
Aún no hay comentarios.