sqlpostgresqlintervaldates

JUSTIFY_INTERVAL en PostgreSQL: normalizar intervalos en dias y meses

JUSTIFY_HOURS, JUSTIFY_DAYS y JUSTIFY_INTERVAL convierten un intervalo crudo en dias y meses legibles.

2 min de lecturaReferencesql · postgresql · interval · dates · justify

Cuando sumas y restas intervalos en PostgreSQL, el resultado suele quedar "crudo": 36 horas, 90 dias, 800 minutos. La familia JUSTIFY_* reordena ese intervalo en algo legible, pasando las horas sobrantes a dias y los dias sobrantes a meses.

Tres funciones y que arrastra cada una

PostgreSQL incluye tres funciones de normalizacion, cada una responsable de un "lugar":

  • JUSTIFY_HOURS(i) toma cada 24 horas y las convierte en 1 dia.
  • JUSTIFY_DAYS(i) toma cada 30 dias y los convierte en 1 mes.
  • JUSTIFY_INTERVAL(i) hace ambos acarreos a la vez y concilia los signos.
SELECT JUSTIFY_HOURS(INTERVAL '36 hours')   AS h,   -- 1 day 12:00:00
       JUSTIFY_DAYS(INTERVAL '90 days')      AS d,   -- 3 mons
       JUSTIFY_INTERVAL(INTERVAL '1 mon 33 days 27 hours') AS full;
-- full -> 2 mons 4 days 03:00:00

Fijate en que ninguna aplana el intervalo a segundos. PostgreSQL guarda un intervalo en tres campos independientes — meses, dias y microsegundos — y JUSTIFY_* solo mueve valores entre esos campos sin cambiar el significado.

Para que sirve: duracion de un pedido

Supongamos que medimos cuanto lleva un pedido en proceso. La resta simple de tiempos da un intervalo donde todo se acumula en horas:

SELECT id,
       created_at,
       NOW() - created_at AS raw_age
FROM orders
WHERE status = 'processing';
-- raw_age podria ser, por ejemplo, '52:30:00'

La cadena 52:30:00 es tecnicamente correcta pero incomoda en un informe. Envuelve el resultado en JUSTIFY_HOURS:

SELECT id,
       JUSTIFY_HOURS(NOW() - created_at) AS readable_age
FROM orders
WHERE status = 'processing';
-- readable_age -> 2 days 04:30:00

Ahora se lee como "2 dias y algunas horas" — justo lo que un responsable espera ver.

Antiguedad de empleados y grandes cantidades de dias

JUSTIFY_DAYS es muy util cuando acumulas dias y quieres una estimacion aproximada en meses. Imagina agregar dias por departamento:

SELECT dept,
       JUSTIFY_DAYS(SUM(NOW() - created_at)) AS dept_tenure
FROM employees
GROUP BY dept;

Cuando un intervalo lleva horas y dias al mismo tiempo, recurre a JUSTIFY_INTERVAL — ordena en todos los frentes. Una buena costumbre es normalizar una diferencia antes de compararla, para que los signos mixtos no te jueguen una mala pasada:

SELECT name,
       JUSTIFY_INTERVAL(salary_review_at - hired_at) AS service
FROM employees
ORDER BY service DESC;

Cuidado: 30 dias no es un mes de calendario

La trampa principal de JUSTIFY_DAYS y JUSTIFY_INTERVAL es que tratan un mes como exactamente 30 dias. Los meses reales nunca son asi: febrero tiene 28 o 29 dias, julio tiene 31.

SELECT JUSTIFY_INTERVAL(INTERVAL '60 days');
-- 2 mons   (no "1 mes mas algunos dias de calendario")

Por eso un intervalo normalizado sirve para informes y etiquetas legibles, pero es erroneo para aritmetica exacta de fechas. Ten clara la distincion:

  • JUSTIFY_* aplica reglas fijas: 24 horas = 1 dia, 30 dias = 1 mes.
  • AGE(end, start) mira el calendario real y devuelve meses y dias verdaderos.

Si necesitas una "edad" honesta, usa AGE. Si solo quieres mostrar una duracion acumulada con orden, usa JUSTIFY_*.

Diferencias en otros motores

Las funciones JUSTIFY_* son propias de PostgreSQL; no hay equivalente directo en otros motores.

  • MySQL: no existe un tipo interval de primera clase, asi que las diferencias suelen vivir como segundos o dias. Normalizas a mano con DIV y MOD, por ejemplo seconds DIV 86400 para dias.
  • ClickHouse: los intervalos tampoco se normalizan solos; usa dateDiff('day', ...) y aritmetica numerica simple para derivar los lugares que quieras.

En resumen: JUSTIFY_* es una comodidad de presentacion que vive en PostgreSQL. En codigo portable, normaliza las duraciones tu mismo y recuerda que "un mes igual a 30 dias" es una simplificacion, no una verdad del calendario.

Practica con ejercicios reales

Resuelve ejercicios en el entrenador de SQL con corrección instantánea y pistas.

Abrir el entrenador