Manejo de Fechas en JSON
Aprende las mejores prácticas para serializar y deserializar fechas en formato JSON, incluyendo ISO 8601, timestamps y formatos personalizados.
TL;DR - Resumen rápido
- JSON no tiene un tipo de fecha nativo, las fechas se serializan como strings
- ISO 8601 es el formato estándar para fechas en JSON (YYYY-MM-DDTHH:mm:ss.sssZ)
- JSON.stringify() convierte Date a strings ISO 8601 automáticamente
- JSON.parse() no restaura Date automáticamente, necesitas un reviver
- Los timestamps numéricos son una alternativa compacta para fechas
Introducción a Fechas en JSON
JSON no tiene un tipo de dato nativo para representar fechas, lo que crea un desafío cuando necesitas serializar y deserializar información temporal. Cuando usas JSON.stringify() con un objeto Date, JavaScript lo convierte automáticamente a un string en formato ISO 8601. Sin embargo, el proceso inverso no es automático: JSON.parse() no restaura los strings de fecha a objetos Date.
Esta limitación significa que debes implementar una estrategia consistente para manejar fechas en tu aplicación. Los desafíos principales incluyen:
- <strong>Serialización automática pero deserialización manual</strong>: JSON.stringify() convierte Date a ISO 8601, pero JSON.parse() los deja como strings
- <strong>Pérdida de funcionalidad</strong>: Los strings de fecha no tienen métodos de Date como getFullYear() o toLocaleDateString()
- <strong>Zonas horarias</strong>: Los timestamps UTC pueden confundirse con horas locales sin contexto adecuado
- <strong>Compatibilidad</strong>: Diferentes sistemas pueden esperar formatos diferentes (ISO 8601, timestamps, Unix time)
¿Por qué ISO 8601?
ISO 8601 es el estándar internacional para representar fechas y horas. Es legible por humanos, ordenable lexicográficamente, y soporta zonas horarias. El formato "2024-02-03T14:30:00.000Z" es reconocido universalmente por la mayoría de APIs y bases de datos, lo que lo hace ideal para interoperabilidad.
Serialización de Fechas
JSON.stringify() convierte automáticamente los objetos Date a strings ISO 8601. Este comportamiento es conveniente pero puede no ser ideal en todos los casos. A veces prefieres timestamps numéricos para ahorrar espacio, o formatos personalizados para compatibilidad con sistemas legacy. El método toJSON() de Date y el parámetro replacer te dan control sobre cómo se serializan las fechas.
El ejemplo muestra cómo JSON.stringify() convierte Date a strings ISO 8601 por defecto. También demuestra cómo usar toJSON() para personalizar la serialización, convirtiendo fechas a timestamps numéricos o formatos personalizados. Este enfoque es útil cuando necesitas compatibilidad con sistemas que no reconocen ISO 8601 o prefieres representaciones más compactas.
Personalización con toJSON()
Los objetos Date tienen un método toJSON() que JSON.stringify() llama automáticamente. Puedes sobrescribir este método en tus propios objetos para controlar cómo se serializan las fechas. Esto es especialmente útil para objetos de dominio que contienen fechas que deben serializarse de manera específica.
El ejemplo muestra cómo sobrescribir toJSON() en objetos personalizados para controlar la serialización de fechas. En el caso de Evento, la fecha se convierte a timestamp para ahorrar espacio. En el caso de Usuario, las fechas se serializan en diferentes formatos según su propósito: ISO 8601 para fechas de nacimiento y timestamps para fechas de registro.
Deserialización de Fechas
A diferencia de la serialización, la deserialización de fechas no es automática. JSON.parse() no reconoce strings de fecha como objetos Date, por lo que necesitas implementar un reviver que detecte y convierta los strings de fecha. El reviver se ejecuta para cada propiedad del objeto parsed, permitiéndote restaurar fechas de manera consistente.
El ejemplo muestra un reviver que detecta strings en formato ISO 8601 y los convierte a objetos Date. El patrón regex /^\d4-\d2-\d2T\d2:\d2:\d2(\.\d3)?Z?$/ identifica strings que coinciden con el formato ISO 8601. Este enfoque es más robusto que intentar convertir cualquier string a Date, ya que evita falsos positivos.
Mejor práctica: Validación estricta de fechas
Usa regex estricto para detectar fechas ISO 8601 en lugar de intentar convertir cualquier string a Date. Esto previene conversiones incorrectas de strings que parecen fechas pero no lo son, como IDs de productos o códigos de referencia.
Reviver para Múltiples Formatos
En aplicaciones que consumen datos de múltiples fuentes, es posible que encuentres diferentes formatos de fecha. Un reviver robusto debe manejar ISO 8601, timestamps numéricos, y formatos personalizados. La clave es detectar el formato correcto y convertirlo consistentemente a objetos Date.
El ejemplo muestra un reviver que maneja tres formatos de fecha: ISO 8601, timestamps numéricos, y un formato personalizado con prefijo "date:". Cada formato se detecta mediante un patrón específico y se convierte a un objeto Date. Este enfoque permite interoperabilidad con sistemas que usan diferentes convenciones de fecha.
Formatos Alternativos
Aunque ISO 8601 es el estándar recomendado, hay situaciones donde otros formatos son más apropiados. Los timestamps numéricos son más compactos y eficientes para cálculos, mientras que los formatos personalizados pueden ser necesarios para compatibilidad con sistemas legacy o APIs específicas. La clave es elegir el formato correcto para tu caso de uso y documentarlo claramente.
El ejemplo compara tres formatos de fecha: ISO 8601 (legible y estándar), timestamp numérico (compacto y eficiente), y un formato personalizado con marcador de tipo (flexible para sistemas legacy). Cada formato tiene ventajas y desventajas en términos de tamaño, legibilidad, y compatibilidad.
- <strong>ISO 8601</strong>: Estándar, legible, soporta zonas horarias
- <strong>Timestamp numérico</strong>: Compacto, eficiente para cálculos, sin zona horaria
- <strong>Formato personalizado</strong>: Flexible para compatibilidad, requiere documentación
- <strong>Unix timestamp</strong>: Universal, segundos desde epoch, sin milisegundos por defecto
Advertencia: Zonas horarias y timestamps
Los timestamps numéricos (Date.getTime()) representan el momento exacto en UTC, sin información de zona horaria. Esto puede causar confusiones cuando los usuarios esperan ver fechas en su zona horaria local. Para aplicaciones que muestran fechas a usuarios, considera usar ISO 8601 con información de zona horaria explícita.
Comparación de Formatos
Elegir el formato correcto depende de tus requisitos específicos. ISO 8601 es ideal para APIs públicas y almacenamiento legible. Los timestamps son mejores para cálculos internos y cuando el tamaño del JSON es crítico. Los formatos personalizados solo deberían usarse cuando sea necesario para compatibilidad con sistemas existentes.
El ejemplo muestra cómo diferentes formatos de fecha afectan el tamaño y legibilidad del JSON resultante. ISO 8601 produce strings más largos pero legibles. Los timestamps son significativamente más compactos pero requieren conversión para lectura humana. Los formatos personalizados pueden incluir metadatos adicionales pero aumentan la complejidad.
Resumen: Fechas en JSON
Conceptos principales:
- •JSON no tiene tipo de fecha nativo, se serializan como strings
- •ISO 8601 es el formato estándar para fechas en JSON
- •JSON.stringify() convierte Date a ISO 8601 automáticamente
- •JSON.parse() no restaura Date, necesitas un reviver
- •Los timestamps son una alternativa compacta pero menos legible
Mejores prácticas:
- •Usa ISO 8601 para APIs públicas y almacenamiento legible
- •Implementa un reviver para restaurar fechas automáticamente
- •Usa timestamps solo cuando el tamaño del JSON es crítico
- •Documenta claramente el formato de fechas en tu API
- •Considera zonas horarias al elegir el formato de fecha