DATEDIFF

La funcion DATEDIFF calcula la diferencia en días entre dos fechas. Devuelve un número entero que representa cuántos días separan la primera fecha de la segunda. Es la función más directa de MySQL para responder preguntas como "cuántos días han pasado desde..." o "cuántos días faltan para...".

Sintaxis

DATEDIFF(fecha1, fecha2)

Ambos argumentos deben ser valores de tipo DATE o DATETIME. Si pasas valores DATETIME, MySQL utiliza únicamente la parte de la fecha para el cálculo, ignorando por completo el componente horario. El resultado es fecha1 - fecha2 expresado en días.

Comportamiento básico

Calcular los días entre dos fechas concretas:

SELECT DATEDIFF('2026-03-25', '2026-03-15') AS diferencia;
diferencia
10

El resultado es 10 porque hay 10 días entre el 15 y el 25 de marzo. El orden de los argumentos importa: DATEDIFF calcula fecha1 - fecha2. Si inviertes el orden, el resultado cambia de signo:

SELECT
    DATEDIFF('2026-03-25', '2026-03-15') AS positivo,
    DATEDIFF('2026-03-15', '2026-03-25') AS negativo;
positivonegativo
10-10

Un resultado positivo indica que fecha1 es posterior a fecha2. Un resultado negativo indica lo contrario. Esta propiedad es fundamental para entender los resultados de DATEDIFF: siempre piensa en ello como "primera fecha menos segunda fecha".

Cuando los argumentos son valores DATETIME, el componente horario se descarta:

SELECT DATEDIFF('2026-03-15 23:59:59', '2026-03-15 00:00:01') AS diferencia;
diferencia
0

Aunque hay casi 24 horas de diferencia, DATEDIFF solo compara las fechas (ambas son 15 de marzo) y devuelve 0. Si necesitas precisión horaria, deberás usar TIMEDIFF o TIMESTAMPDIFF.

Caso práctico: antigüedad de pedidos

Un uso muy frecuente es calcular cuántos días han transcurrido desde que se creó un pedido. Esto permite identificar pedidos estancados o medir tiempos de procesamiento:

SELECT
    id,
    cliente_id,
    estado,
    fecha_creacion,
    DATEDIFF(CURDATE(), fecha_creacion) AS dias_desde_creacion
FROM pedidos
WHERE estado != 'entregado'
ORDER BY dias_desde_creacion DESC
LIMIT 5;
idcliente_idestadofecha_creaciondias_desde_creacion
892156pendiente2025-12-2056
94589en_proceso2026-01-0540
978234en_proceso2026-01-1530
100167enviado2026-01-2817
1015312enviado2026-02-0311

Al usar CURDATE() como primer argumento, el resultado siempre refleja los días transcurridos hasta hoy. Un pedido pendiente desde hace 56 días seguramente requiere atención inmediata.

Caso práctico: días hasta vencimiento

Invertir el orden de los argumentos permite calcular cuántos días faltan para una fecha futura, como la expiración de una membresía:

SELECT
    c.nombre,
    m.tipo_plan,
    m.fecha_vencimiento,
    DATEDIFF(m.fecha_vencimiento, CURDATE()) AS dias_restantes,
    CASE
        WHEN DATEDIFF(m.fecha_vencimiento, CURDATE()) < 0 THEN 'Vencida'
        WHEN DATEDIFF(m.fecha_vencimiento, CURDATE()) <= 7 THEN 'Por vencer'
        ELSE 'Vigente'
    END AS estado
FROM membresias m
JOIN clientes c ON m.cliente_id = c.id
ORDER BY dias_restantes
LIMIT 6;
nombretipo_planfecha_vencimientodias_restantesestado
Roberto Díazmensual2026-02-10-4Vencida
Elena Ruizmensual2026-02-12-2Vencida
Carlos Lópeztrimestral2026-02-162Por vencer
Ana Martínezmensual2026-02-206Por vencer
Pedro Navarroanual2026-05-30105Vigente
Lucía Fernándezanual2026-08-15182Vigente

El valor negativo en dias_restantes indica que la membresía ya venció. La combinación de DATEDIFF con CASE permite clasificar automáticamente el estado de cada registro.

Caso práctico: tiempo de entrega promedio

DATEDIFF combinada con funciones de agregación permite calcular métricas de rendimiento operativo. Por ejemplo, el tiempo promedio de entrega por categoría de producto:

SELECT
    cat.nombre AS categoria,
    COUNT(p.id) AS total_pedidos,
    ROUND(AVG(DATEDIFF(p.fecha_entrega, p.fecha_creacion)), 1) AS promedio_dias_entrega,
    MIN(DATEDIFF(p.fecha_entrega, p.fecha_creacion)) AS minimo,
    MAX(DATEDIFF(p.fecha_entrega, p.fecha_creacion)) AS maximo
FROM pedidos p
JOIN productos prod ON p.producto_id = prod.id
JOIN categorias cat ON prod.categoria_id = cat.id
WHERE p.fecha_entrega IS NOT NULL
GROUP BY cat.nombre
ORDER BY promedio_dias_entrega;
categoriatotal_pedidospromedio_dias_entregaminimomaximo
Libros2452.315
Electrónica5123.8112
Ropa3894.1210
Hogar1785.7215
Deportes1346.2318

AVG(DATEDIFF(...)) calcula el promedio de los días de entrega para cada grupo, mientras que MIN y MAX muestran el rango. Este tipo de análisis es esencial para evaluar la eficiencia logística.

Caso práctico: agrupar por ventanas temporales

Puedes usar DATEDIFF para segmentar registros en rangos de días, lo que es útil para análisis de cohortes o clasificación de deudas:

SELECT
    CASE
        WHEN DATEDIFF(CURDATE(), fecha_factura) <= 30 THEN '0-30 días'
        WHEN DATEDIFF(CURDATE(), fecha_factura) <= 60 THEN '31-60 días'
        WHEN DATEDIFF(CURDATE(), fecha_factura) <= 90 THEN '61-90 días'
        ELSE 'Más de 90 días'
    END AS antiguedad,
    COUNT(*) AS cantidad,
    SUM(monto_pendiente) AS total_pendiente
FROM facturas
WHERE pagada = 0
GROUP BY antiguedad
ORDER BY MIN(DATEDIFF(CURDATE(), fecha_factura));
antiguedadcantidadtotal_pendiente
0-30 días4528750.00
31-60 días2318200.50
61-90 días129800.00
Más de 90 días815600.75

Este patrón de segmentación por antigüedad es estándar en el análisis financiero de cuentas por cobrar.

Manejo de NULL

Si cualquiera de los argumentos es NULL, DATEDIFF devuelve NULL:

SELECT
    DATEDIFF(NULL, '2026-03-15') AS primero_nulo,
    DATEDIFF('2026-03-15', NULL) AS segundo_nulo;
primero_nulosegundo_nulo
NULLNULL

En consultas con columnas que pueden contener NULL (como una fecha de entrega que aún no ha ocurrido), filtra los nulos o proporciona un valor alternativo:

SELECT
    id,
    COALESCE(
        DATEDIFF(fecha_entrega, fecha_creacion),
        DATEDIFF(CURDATE(), fecha_creacion)
    ) AS dias_transcurridos
FROM pedidos;

Esta consulta usa los días hasta la entrega si la fecha de entrega existe, y si no, los días desde la creación hasta hoy.

Combinación con otras funciones

DATEDIFF se combina frecuentemente con ABS cuando no te importa el signo de la diferencia:

SELECT ABS(DATEDIFF('2026-01-10', '2026-03-15')) AS distancia_en_dias;
distancia_en_dias
64

Para convertir la diferencia de días en semanas, meses aproximados o años aproximados, puedes hacer aritmética simple:

SELECT
    DATEDIFF('2027-02-14', '2026-02-14') AS dias,
    DATEDIFF('2027-02-14', '2026-02-14') / 7 AS semanas,
    DATEDIFF('2027-02-14', '2026-02-14') / 30.44 AS meses_aprox,
    DATEDIFF('2027-02-14', '2026-02-14') / 365.25 AS anios_aprox;
diassemanasmeses_aproxanios_aprox
36552.142911.99080.9993

Sin embargo, para obtener diferencias precisas en meses o años, la función TIMESTAMPDIFF es una opción más fiable que estas aproximaciones.

En el siguiente artículo veremos TIMEDIFF para calcular la diferencia de tiempo entre dos valores.

Escrito por Eduardo Lázaro