TIMESTAMPADD

La funcion TIMESTAMPADD suma un intervalo expresado en una unidad específica a un valor de fecha o datetime. Es la contrapartida natural de TIMESTAMPDIFF: mientras que TIMESTAMPDIFF mide cuántas unidades separan dos fechas, TIMESTAMPADD avanza (o retrocede) una fecha la cantidad de unidades que indiques.

Sintaxis

TIMESTAMPADD(unidad, intervalo, datetime)

El primer argumento es la unidad del intervalo. Las unidades válidas son SECOND, MINUTE, HOUR, DAY, WEEK, MONTH, QUARTER y YEAR. El segundo argumento es un número entero que indica cuántas unidades sumar (puede ser negativo para restar). El tercer argumento es el valor DATE o DATETIME al que se aplica la operación.

Comportamiento básico

Sumar 15 días a una fecha:

SELECT TIMESTAMPADD(DAY, 15, '2026-03-01') AS resultado;
resultado
2026-03-16

La sintaxis es directa: unidad, cantidad, fecha. Para sumar meses, años o cualquier otra unidad, simplemente cambias el primer argumento:

SELECT
    TIMESTAMPADD(MONTH, 3, '2026-01-15') AS mas_3_meses,
    TIMESTAMPADD(YEAR, 2, '2026-01-15') AS mas_2_anios,
    TIMESTAMPADD(QUARTER, 1, '2026-01-15') AS mas_1_trimestre;
mas_3_mesesmas_2_aniosmas_1_trimestre
2026-04-152028-01-152026-04-15

Al sumar meses, TIMESTAMPADD ajusta el día cuando el mes destino tiene menos días que el mes origen, igual que DATE_ADD:

SELECT TIMESTAMPADD(MONTH, 1, '2026-01-31') AS resultado;
resultado
2026-02-28

Enero tiene 31 días pero febrero solo 28, así que MySQL ajusta al último día válido del mes.

Para sumar horas, minutos o segundos, el argumento de entrada debería incluir el componente horario:

SELECT
    TIMESTAMPADD(HOUR, 5, '2026-03-15 10:00:00') AS mas_5_horas,
    TIMESTAMPADD(MINUTE, 90, '2026-03-15 10:00:00') AS mas_90_min,
    TIMESTAMPADD(SECOND, 3600, '2026-03-15 10:00:00') AS mas_3600_seg;
mas_5_horasmas_90_minmas_3600_seg
2026-03-15 15:00:002026-03-15 11:30:002026-03-15 11:00:00

Observa que sumar 90 minutos y sumar 3600 segundos (1 hora) producen resultados correctos, cruzando los límites de hora cuando es necesario.

Diferencia con DATE_ADD

TIMESTAMPADD y DATE_ADD logran el mismo resultado en la mayoría de los casos, pero tienen diferencias de sintaxis y estilo que vale la pena entender:

SELECT
    DATE_ADD('2026-03-15', INTERVAL 6 MONTH) AS con_date_add,
    TIMESTAMPADD(MONTH, 6, '2026-03-15') AS con_timestampadd;
con_date_addcon_timestampadd
2026-09-152026-09-15

El resultado es idéntico. Las diferencias principales son estas: DATE_ADD usa la sintaxis INTERVAL expr unidad y admite intervalos compuestos como DAY_HOUR o YEAR_MONTH, que TIMESTAMPADD no soporta. Por otro lado, TIMESTAMPADD tiene una sintaxis funcional pura con tres argumentos separados por comas, lo que puede ser más fácil de construir dinámicamente en código de aplicación.

En general, usa DATE_ADD cuando trabajes directamente en SQL y necesites intervalos compuestos o la sintaxis + INTERVAL. Usa TIMESTAMPADD cuando necesites simetría con TIMESTAMPDIFF o cuando la sintaxis funcional encaje mejor en tu código.

Restar tiempo con valores negativos

Un valor negativo en el segundo argumento convierte la suma en una resta:

SELECT
    TIMESTAMPADD(DAY, -10, '2026-03-15') AS menos_10_dias,
    TIMESTAMPADD(MONTH, -3, '2026-06-15') AS menos_3_meses,
    TIMESTAMPADD(HOUR, -8, '2026-03-15 20:00:00') AS menos_8_horas;
menos_10_diasmenos_3_mesesmenos_8_horas
2026-03-052026-03-152026-03-15 12:00:00

Esto hace que TIMESTAMPADD sea una función bidireccional: con un solo conocimiento de la función puedes tanto avanzar como retroceder en el tiempo.

Caso práctico: programación de tareas recurrentes

En un sistema de gestión de tareas, cada tarea tiene una frecuencia de recurrencia expresada en unidad y cantidad. TIMESTAMPADD permite calcular la próxima ejecución de forma genérica:

SELECT
    t.nombre_tarea,
    t.ultima_ejecucion,
    t.frecuencia_valor,
    t.frecuencia_unidad,
    CASE t.frecuencia_unidad
        WHEN 'HOUR' THEN TIMESTAMPADD(HOUR, t.frecuencia_valor, t.ultima_ejecucion)
        WHEN 'DAY' THEN TIMESTAMPADD(DAY, t.frecuencia_valor, t.ultima_ejecucion)
        WHEN 'WEEK' THEN TIMESTAMPADD(WEEK, t.frecuencia_valor, t.ultima_ejecucion)
        WHEN 'MONTH' THEN TIMESTAMPADD(MONTH, t.frecuencia_valor, t.ultima_ejecucion)
    END AS proxima_ejecucion
FROM tareas_programadas t
WHERE t.activa = 1
ORDER BY proxima_ejecucion;
nombre_tareaultima_ejecucionfrecuencia_valorfrecuencia_unidadproxima_ejecucion
Backup incremental2026-02-14 02:00:006HOUR2026-02-14 08:00:00
Reporte diario2026-02-14 08:00:001DAY2026-02-15 08:00:00
Limpieza logs2026-02-10 03:00:001WEEK2026-02-17 03:00:00
Facturación2026-01-15 00:00:001MONTH2026-02-15 00:00:00

El CASE selecciona la unidad dinámicamente según lo configurado en cada tarea. Este patrón es la base de cualquier sistema de scheduling basado en base de datos.

Caso práctico: generar series de fechas

TIMESTAMPADD es esencial para generar secuencias de fechas cuando necesitas crear un calendario o llenar huecos en reportes temporales. Combinada con una tabla de números auxiliar:

SELECT
    TIMESTAMPADD(DAY, n.num, '2026-02-01') AS fecha
FROM (
    SELECT 0 AS num UNION SELECT 1 UNION SELECT 2 UNION SELECT 3
    UNION SELECT 4 UNION SELECT 5 UNION SELECT 6
) n
ORDER BY fecha;
fecha
2026-02-01
2026-02-02
2026-02-03
2026-02-04
2026-02-05
2026-02-06
2026-02-07

Esta técnica se utiliza frecuentemente en un LEFT JOIN contra una tabla de hechos para garantizar que los reportes incluyan todos los días del periodo, incluso aquellos sin datos:

SELECT
    calendario.fecha,
    COALESCE(SUM(p.total), 0) AS ventas_dia
FROM (
    SELECT TIMESTAMPADD(DAY, n.num, '2026-02-01') AS fecha
    FROM (SELECT 0 AS num UNION SELECT 1 UNION SELECT 2 UNION SELECT 3
          UNION SELECT 4 UNION SELECT 5 UNION SELECT 6) n
) calendario
LEFT JOIN pedidos p ON DATE(p.fecha_creacion) = calendario.fecha
GROUP BY calendario.fecha
ORDER BY calendario.fecha;
fechaventas_dia
2026-02-011250.00
2026-02-020.00
2026-02-03875.50
2026-02-042100.00
2026-02-05450.00
2026-02-060.00
2026-02-071890.75

Sin la serie generada, los días sin ventas no aparecerían en el resultado. TIMESTAMPADD permite construir el esqueleto temporal completo.

Caso práctico: cálculo de fechas de vencimiento con gracia

Muchos sistemas aplican un periodo de gracia después del vencimiento. Puedes encadenar llamadas a TIMESTAMPADD para calcular ambas fechas:

SELECT
    c.nombre,
    f.numero_factura,
    f.fecha_emision,
    TIMESTAMPADD(DAY, 30, f.fecha_emision) AS fecha_vencimiento,
    TIMESTAMPADD(DAY, 45, f.fecha_emision) AS fin_periodo_gracia
FROM facturas f
JOIN clientes c ON f.cliente_id = c.id
WHERE f.pagada = 0
ORDER BY f.fecha_emision
LIMIT 4;
nombrenumero_facturafecha_emisionfecha_vencimientofin_periodo_gracia
Empresa ABCF-2026-00892026-01-052026-02-042026-02-19
Corp XYZF-2026-01022026-01-152026-02-142026-03-01
Servicios JKLF-2026-01182026-01-252026-02-242026-03-11
Tech MNOF-2026-01342026-02-012026-03-032026-03-18

Manejo de NULL

Si el valor datetime o el intervalo es NULL, TIMESTAMPADD devuelve NULL:

SELECT
    TIMESTAMPADD(DAY, 5, NULL) AS fecha_nula,
    TIMESTAMPADD(DAY, NULL, '2026-03-15') AS intervalo_nulo;
fecha_nulaintervalo_nulo
NULLNULL

Para proteger tus consultas, utiliza COALESCE o IFNULL según el contexto:

SELECT
    nombre,
    TIMESTAMPADD(MONTH, 12,
        COALESCE(fecha_ultimo_contrato, fecha_registro)
    ) AS fecha_revision
FROM clientes;

Combinación con otras funciones

TIMESTAMPADD funciona bien junto a TIMESTAMPDIFF para crear lógica de ida y vuelta temporal. Por ejemplo, calcular cuántos meses de antigüedad tiene un cliente y luego proyectar cuándo alcanzará el siguiente nivel:

SELECT
    c.nombre,
    c.fecha_registro,
    TIMESTAMPDIFF(MONTH, c.fecha_registro, CURDATE()) AS meses_antiguedad,
    CASE
        WHEN TIMESTAMPDIFF(MONTH, c.fecha_registro, CURDATE()) < 12
        THEN TIMESTAMPADD(MONTH, 12, c.fecha_registro)
        WHEN TIMESTAMPDIFF(MONTH, c.fecha_registro, CURDATE()) < 24
        THEN TIMESTAMPADD(MONTH, 24, c.fecha_registro)
        ELSE NULL
    END AS fecha_proximo_nivel
FROM clientes c
WHERE c.activo = 1
ORDER BY meses_antiguedad DESC
LIMIT 4;
nombrefecha_registromeses_antiguedadfecha_proximo_nivel
María García2023-05-1033NULL
Carlos López2024-08-20172026-08-20
Ana Martínez2025-06-0182026-06-01
Pedro Ruiz2025-11-1522026-11-15

Los clientes con más de 24 meses ya alcanzaron el nivel máximo (resultado NULL), mientras que los demás ven proyectada la fecha en la que subirán de nivel.

En el siguiente artículo veremos EXTRACT para extraer partes específicas de una fecha.

Escrito por Eduardo Lázaro