Zonas horarias en TypeScript: cómo no volverse loco con las fechas

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

Introducción: por qué el tiempo es un dolor de cabeza para cada desarrollador

\n\n

¿Alguna vez has atrapado un error cuando un usuario de Vladivostok ve la fecha del día siguiente, aunque en el calendario sea hoy? ¿O cuando un servidor en AWS us-east-1 envía una hora que tu cliente en Kaliningrado interpreta como las 3 de la madrugada? Bienvenido al mundo de las zonas horarias en TypeScript.

\n\n

El problema es que JavaScript (y TypeScript como su superconjunto) fue diseñado originalmente para navegadores. El objeto nativo Date es, en esencia, una marca de tiempo disfrazada en UTC. No sabe trabajar con husos horarios como necesitamos. Y si estás escribiendo una aplicación seria en TypeScript —ya sea un panel de administración en React, un backend en Node.js o una aplicación móvil en React Native— no podrás prescindir de un manejo adecuado de las zonas horarias.

\n\n

En este artículo te mostraré cómo domesticar el tiempo. Entenderemos los conceptos básicos, aprenderemos a usar bibliotecas modernas y evitaremos las trampas típicas. ¡Allá vamos!

\n\n

Qué necesitas saber sobre las zonas horarias antes de escribir código

\n\n

Antes de sumergirnos en TypeScript, aclaremos las cosas. En el mundo existen dos tipos de tiempo: absoluto (UTC) y local (el que ve el usuario).

\n\n
    \n
  • UTC (Tiempo Universal Coordinado) — es el estándar. Los servidores, bases de datos y API deben almacenar la hora en UTC. Esta es una regla de hierro.
  • \n
  • Base de datos de zonas horarias IANA — es un diccionario de husos horarios como Europe/Moscow, Asia/Vladivostok. Estas cadenas, y no abreviaturas como MSK o PST, deben usarse en el código.
  • \n
  • Offset (desplazamiento) — es la diferencia con UTC, por ejemplo +03:00. Pero recuerda: el desplazamiento puede cambiar debido al horario de verano (DST). Por lo tanto, almacenar el offset en lugar de la zona IANA es una mala idea.
  • \n
\n\n
\n

Regla de oro: almacenamos en UTC, convertimos en el cliente, usamos cadenas IANA para identificar las zonas.

\n
\n\n

Por qué el Date nativo no es suficiente: dolor y sufrimiento

\n\n

Enfrentemos la realidad: new Date() en TypeScript es como una navaja suiza con la hoja rota. Solo sabe almacenar una marca de tiempo y mostrarla en la zona local del navegador o servidor. Intenta hacer algo más complejo:

\n\n
// Mal ejemplo: intentando trabajar con zonas usando medios nativos\nconst date = new Date('2024-03-10T12:00:00');\nconsole.log(date.toLocaleString('ru-RU', { timeZone: 'Europe/Moscow' }));\n// Muestra: "10.03.2024, 15:00:00" — ¡pero esto es solo una cadena, no un objeto!\n\n// ¿Y si necesitas obtener un Date en otra zona?\n// Ups... JS nativo no puede crear un Date vinculado a una zona.\n
\n\n

El problema es que Date siempre almacena la hora en UTC. Todos los métodos como getHours() simplemente convierten UTC a la hora local del navegador. No puedes obtener un objeto Date que "piense" que está en Nueva York.

\n\n

Por eso usamos bibliotecas. En el ecosistema TypeScript hay dos candidatos principales: Luxon y date-fns-tz.

\n\n

Luxon: artillería pesada para trabajar con fechas

\n\n

Luxon es una biblioteca moderna del creador de Moment.js (que ya está obsoleto). Está escrita desde cero, usa el nativo Intl.DateTimeFormat y está perfectamente tipada para TypeScript.

\n\n

Instalación de Luxon

\n\n
npm install luxon\nnpm install --save-dev @types/luxon\n
\n\n

Creación de una fecha en una zona horaria específica

\n\n
import { DateTime } from 'luxon';\n\n// Creamos una fecha en la zona Europe/Moscow\nconst moscowTime = DateTime.fromObject(\n  { year: 2024, month: 3, day: 10, hour: 12 },\n  { zone: 'Europe/Moscow' }\n);\nconsole.log(moscowTime.toISO());\n// Salida: "2024-03-10T12:00:00.000+03:00"\n\n// Convertimos a otra zona\nconst nyTime = moscowTime.setZone('America/New_York');\nconsole.log(nyTime.toISO());\n// Salida: "2024-03-10T05:00:00.00                

Blogs

Book Recommendations