English

Manual de campo · trampas de SQL

Zonas horarias: guarda UTC, muestra local

Agrupar por día sin decidir el huso horario reparte la misma sesión entre dos días, y el cambio de hora crea un día de 23 horas y otro de 25.

Cuándo aparece

Cualquier dato con marca de tiempo que cruce husos horarios o un cambio de hora: casi todos los sistemas con usuarios en más de una zona.

Ejemplo

Mal: date_trunc sin decidir el huso

SELECT date_trunc('day', momento_utc) AS dia
FROM sesiones
GROUP BY dia;
-- momento_utc no lleva huso: date_trunc corta en el día UTC.
-- En Ciudad de México (UTC−6) todo lo que pasa después de las
-- 18:00 se apunta al día siguiente

Bien: las dos conversiones, en ese orden

SELECT date_trunc(
  'day',
  momento_utc AT TIME ZONE 'UTC' AT TIME ZONE 'America/Mexico_City'
) AS dia_local
FROM sesiones
GROUP BY dia_local;

Hacen falta las dos conversiones y en ese orden: la primera dice qué instante representa ese TIMESTAMP guardado sin huso (interpretarlo como UTC), la segunda lo traduce al reloj de allí. Con una sola conversión, el motor devuelve un instante y el date_trunc corta usando el huso de la máquina, y el mismo dato da un día distinto en cada ordenador, y un cambio de hora reparte la misma sesión de la noche entre dos fechas.

Esta trampa está escondida en un caso de verdad, con datos de verdad.

Jugar el caso 1 gratis →

Trampas relacionadas