Aritmetica De Fechas en Postgres

Introducción

La aritmética de fechas es una de las ramas que en general causa mas problemas a los programadores tanto de bases de datos como de aplicaciones de negocios.

Es muy importante en este tipo de aplicaciones tomar en cuenta plazos, diferentes zonas horarias, fines de semana, feriados.

Tipos de datos de fechas y horas en PostgreSQL

Lo primero que necesitamos saber son los tipos de datos disponibles para el tratamiento de las fechas y de los intervalos de tiempo. Existen 6 tipos de datos para trabajar con fechas y horas, estos valores están tomados de la documentación oficial de Postgres

Nombre tamaño de almacenamiento Descripción Valor mínimo
timestamp[(p)][sin zona horaria] 8 bytes Fecha y hora (sin zona horaria) 4713 AC
timestamp[(p)][con zona horaria] 8 bytes Fecha y hora (con zona horaria) 4713 AC
date 4 bytes Fecha (sin hora) 4713 AC
time [(p)] [sin zona horaria] 8 bytes Hora (sin fecha ni zona horaria) 00:00:00
time [(p)] [con zona horaria] 12 bytes Hora (sin fecha y con zona horaria) 00:00:00+1459
interval [campos][(p)] 16 bytes Intervalo de tiempo -178000000 años

La precisión p es un parámetro opcional que especifica el número de dígitos que se utilizan en el campo de los segundos. Por default no hay una cota específica para la precisión y el rango de p va de 0 a 6.

El manejo de zonas horarias es complicado, una de las razones es la adición del horario de verano. Las zonas horarias se maejan como desplazamientos de UTC, por lo que por default no se puede adaptar el horario de verano si se hace aritmética a través de zonas horarias con horario de verano.

Las zonas horarias se pueden especificar de 3 formas:

Como podemos ver, postgres tiene un tratamiento muy completo de las fechas y horas, permitiendo almacenar sólo fechas, sólo horas, o su combianción con diferentes niveles de precisión y tomando o no en cuenta la zona horaria. Aqui creo que es importante hacer un comentario sobre el tipo de dato interval El tipo de dato interval es parte del estándar SQL y se utiliza para almacenar precisamente intervalos de tiempo, otra de sus funciones es permitir especificar intevalos o rangos de tiempo dentro de consultas.

Para declarar un intervalo se pueden declarar intervalos como:

interval '2 months ago';
interval '3 hours 20 minutes';

El formato de los intervalos puede ser de 4 formas:

En general, todos tienen una sintaxis como:

cantidad unidades [ cantidad unidades ] [ direccion ]

Podemos verlos en detalle aquí

SET intervalstyle = 'sql_standard';
 
SELECT
 INTERVAL '6 years 5 months 4 days 3 hours 2 minutes 1 second';
 
 
SET intervalstyle = 'postgres';
 
SELECT
 INTERVAL '6 years 5 months 4 days 3 hours 2 minutes 1 second';
 
 
SET intervalstyle = 'postgres_verbose';
 
SELECT
 INTERVAL '6 years 5 months 4 days 3 hours 2 minutes 1 second';
 
 
SET intervalstyle = 'iso_8601';
 
SELECT
 INTERVAL '6 years 5 months 4 days 3 hours 2 minutes 1 second';

Operaciones

Existen 4 operadores básicos para la aritmética de fechas: =, -, /, *. Estos operadores funcionan sobre los enteros, sobre los intervalos, los timestamps y las fechas.

La siguiente tabla está tomada del manual de Postgres 10.

Operator Example Result
+ date ‘2001-09-28’ + integer ‘7’ date ‘2001-10-05’
+ date ‘2001-09-28’ + interval ‘1 hour’ timestamp ‘2001-09-28 01:00:00’
+ date ‘2001-09-28’ + time ‘03:00’ timestamp ‘2001-09-28 03:00:00’
+ interval ‘1 day’ + interval ‘1 hour’ interval ‘1 day 01:00:00’
+ timestamp ‘2001-09-28 01:00’ + interval ‘23 hours’ timestamp ‘2001-09-29 00:00:00’
+ time ‘01:00’ + interval ‘3 hours’ time ‘04:00:00’
- - interval ‘23 hours’ interval ‘-23:00:00’
- date ‘2001-10-01’ - date ‘2001-09-28’ integer ‘3’ (days)
- date ‘2001-10-01’ - integer ‘7’ date ‘2001-09-24’
- date ‘2001-09-28’ - interval ‘1 hour’ timestamp ‘2001-09-27 23:00:00’
- time ‘05:00’ - time ‘03:00’ interval ‘02:00:00’
- time ‘05:00’ - interval ‘2 hours’ time ‘03:00:00’
- timestamp ‘2001-09-28 23:00’ - interval ‘23 hours’ timestamp ‘2001-09-28 00:00:00’
- interval ‘1 day’ - interval ‘1 hour’ interval ‘1 day -01:00:00’
- timestamp ‘2001-09-29 03:00’ - timestamp ‘2001-09-27 12:00’ interval ‘1 day 15:00:00’
* 900 * interval ‘1 second’ interval ‘00:15:00’
* 21 * interval ‘1 day’ interval ‘21 days’
* double precision ‘3.5’ * interval ‘1 hour’ interval ‘03:30:00’
/ interval ‘1 hour’ / double precision ‘1.5’ interval ‘00:40:00’

Además, existe una serie de funciones específicas para conversiones de fechas y manejos específicos para reglas de negocio, que se pueden ver aqui

Conclusiones

La aritmética de fechas es uno de los quebraderos de cabeza tradicionales de la programación de reglas de negocio por lo que conocer estas funciones puede llegar a salvar el día durante el desarrollo de aplicaicones y durante el diseño de bases de datos complejas.