Trabando con diferentes zonas horarias

Trabando con diferentes zonas horarias

Título: Cómo Abordar el Desafío de las Zonas Horarias en Desarrollo de Software

Manejar información en distintas zonas horarias y cómo asegurarse de que los usuarios vean los datos en sus propias horas locales siempre suele dar algunos dolores de cabeza; es por ello que en este artículo me gustaría explicar algunos enfoques de como resolver este problema, desde cómo almacenar datos y configurar la base de datos hasta cómo presentarlos a los usuarios y realizar consultas que consideren zonas horarias.

Estrategias de Almacenamiento

Uno de los fundamentos para manejar zonas horarias en aplicaciones es mantener una referencia temporal común. Para lograr esto, se recomienda almacenar todas las fechas y horas en la base de datos en Coordinated Universal Time (UTC). Esto asegura que las fechas y horas tengan una base consistente y evita problemas que podrían surgir debido a cambios de horario de verano u otras complejidades de zonas horarias.

En PostgreSQL, puedes usar el tipo de dato timestamp with time zone (o timestamptz) para almacenar las fechas y horas junto con las zonas horarias, y definitivamente es el que ofrece la implementación mas sencilla.

Ejemplo: Creación de Tabla en PostgreSQL

CREATE TABLE posts (
    id serial PRIMARY KEY,
    content text,
    created_at timestamptz
);

En MySQL es un poco diferente ya que se debe de utilizar el tipo de dato DATETIME:

CREATE TABLE posts (
    id INT PRIMARY KEY AUTO_INCREMENT,
    content TEXT,
    created_at DATETIME
);

Es importante mencionar que en MySQL, el tipo de dato DATETIME no almacena la información de la zona horaria de manera directa. Por lo tanto, si deseas almacenar y gestionar las zonas horarias en MySQL, hay un par de enfoques que podrías considerar:

  1. Almacenar la Zona Horaria por separado: Almacenar la zona horaria en un campo adicional en la tabla permite mantener un registro explícito de la zona horaria asociada a cada registro. Esto puede ser útil si deseas tener un mayor control sobre cómo se manejan las conversiones y presentaciones de las fechas y horas (a mí, particularmente no me gusta porque es un campo extra que puede evitarse).

  2. Usar el Tipo TIMESTAMP con Zona Horaria (MySQL 8.0.19+): Utilizar el tipo de dato TIMESTAMP con la zona horaria integrada puede simplificar el manejo de las zonas horarias, ya que MySQL se encargará automáticamente de las conversiones al almacenar y recuperar los valores. Es importante asegurarse de que la configuración de zonas horarias en el servidor esté correctamente ajustada.

  3. Configurar el motor para siempre almacene en UTC: Configurar el servidor MySQL para almacenar siempre las fechas y horas en UTC es una estrategia eficaz para mantener la coherencia y facilitar las conversiones. Las conversiones de la hora local a UTC deben realizarse antes de insertar los registros en la base de datos.

Mi particular preferencia es una combinación entre el punto 2 y 3, donde utilizo TIMESTAMP pero el motor ha sido configurado para siempre utilizar UTC.

Estrategias de conversión

Yo veo 2 estrategias básicas y simples para que el usuario final obtenga la información en su zona horaria, obviamente su implementación depende de que se tenga de los usuarios.

Estrategia de Conversiones en el Servidor

Esta estrategia da por hecho que conocemos la zona horaria del usuario, entonces las conversiones se pueden realizar en el servidor o incluso a nivel de BD, asegurando que los datos presentados sean consistentes para todos los usuarios.

-- Supongamos que user_timezone contiene la zona horaria del usuario
SELECT *
FROM posts
WHERE EXTRACT(HOUR FROM created_at AT TIME ZONE 'UTC' AT TIME ZONE user_timezone) > 16;

Ya sea que la zona horaria del usuario existe también en la BD como parte de un campo adicional al usuario o en caso de ser una API, pues podrías establecer una zona horaria por defecto pero permitir una cabecera (x-iana-timezone) que se usaría para transmitir la zona horaria del usuario porque fue extraída desde la aplicación cliente.

Estrategia de Conversiones en el Cliente (JavaScript)

Por otro lado, si prefieres realizar conversiones en el cliente porque en el servidor no tienes esta información, puedes hacer uso de bibliotecas como Luxon, Spacetime, Moment Timezone, etc (hay muchas más). Estas librerías te permiten convertir fechas y horas a la zona horaria local del usuario. Y la idea general es que el servidor retornara las fechas en forma de UTC y localmente la aplicación cliente deberá hacerse cargo de realizar la conversión, por ej.:

// Ejemplo utilizando Luxon
const utcTimestamp = 1679804400;  // Ejemplo de timestamp en UTC
const userDateTime = luxon.DateTime.fromSeconds(utcTimestamp).setZone("America/New_York");
console.log(userDateTime.toString());  // Muestra la fecha en la zona horaria del usuario

Ya para finalizar

El desafío de manejar información en diferentes zonas horarias es un aspecto importante en el desarrollo de aplicaciones de software globales. Al seguir prácticas sólidas como almacenar en UTC, configurar la base de datos adecuadamente, registrar la zona horaria de los usuarios y elegir entre realizar conversiones en el servidor o en el cliente, puedes brindar una experiencia de usuario coherente y sin complicaciones, sin importar en qué parte del mundo se encuentren tus usuarios. Además, convertir las fechas a valores numéricos Unix en lugar de texto garantiza una comunicación más eficiente y evita problemas de codificación.

Happy coding! :D


Photo by Aron Visuals on Unsplash

Jack Fiallos

Jack Fiallos

Te gustó este artículo?