La función CURDATE() devuelve la fecha actual del servidor MySQL sin incluir el componente de hora. Su resultado tiene el formato YYYY-MM-DD y es equivalente a invocar DATE(NOW()), pero de forma más directa y legible. Cuando tu consulta solo necesita la fecha y no la hora, CURDATE() expresa esa intención con claridad.

Esta función resulta especialmente útil para comparaciones de fechas donde la hora del día es irrelevante, como verificar si un registro corresponde a hoy, calcular la edad de un cliente o filtrar eventos programados para una fecha específica.

Sintaxis

CURDATE()

CURDATE() no acepta parámetros. Siempre devuelve un valor de tipo DATE con la fecha actual del servidor. Su sinónimo estándar SQL es CURRENT_DATE (sin paréntesis), que produce exactamente el mismo resultado.

Comportamiento básico

La forma más simple de utilizar CURDATE() es en un SELECT directo para conocer la fecha del servidor.

SELECT CURDATE() AS fecha_actual;
fecha_actual
2025-07-15

La diferencia fundamental con NOW() es que CURDATE() descarta por completo la hora, minutos y segundos.

SELECT CURDATE() AS solo_fecha, NOW() AS fecha_y_hora;
solo_fechafecha_y_hora
2025-07-152025-07-15 14:32:08

También puedes usar la forma estándar CURRENT_DATE, que funciona tanto con como sin paréntesis.

SELECT CURRENT_DATE AS forma_1, CURRENT_DATE() AS forma_2, CURDATE() AS forma_3;
forma_1forma_2forma_3
2025-07-152025-07-152025-07-15

Las tres expresiones son intercambiables. La elección es cuestión de preferencia, aunque CURDATE() es la más habitual en la comunidad MySQL.

Cuando CURDATE() se usa en un contexto numérico, MySQL convierte el resultado a un entero con formato YYYYMMDD.

SELECT CURDATE() + 0 AS fecha_numerica;
fecha_numerica
20250715

Caso práctico: filtrar registros del día actual

El uso más frecuente de CURDATE() es encontrar registros que pertenecen al día de hoy. Considera una tabla de ventas donde necesitas obtener todas las transacciones realizadas en la jornada actual.

CREATE TABLE ventas (
    id INT AUTO_INCREMENT PRIMARY KEY,
    producto_id INT NOT NULL,
    cantidad INT NOT NULL,
    precio_unitario DECIMAL(8,2) NOT NULL,
    fecha_venta DATETIME NOT NULL
);
 
SELECT id, producto_id, cantidad, precio_unitario,
       cantidad * precio_unitario AS subtotal
FROM ventas
WHERE DATE(fecha_venta) = CURDATE()
ORDER BY fecha_venta;
idproducto_idcantidadprecio_unitariosubtotal
41215249.9099.80
41381189.00189.00
41422512.5062.50

Observa que la columna fecha_venta es de tipo DATETIME, por lo que envolvemos la comparación con DATE() para ignorar el componente de hora. Sin esta conversión, la igualdad fallaría porque 2025-07-15 14:32:08 no es igual a 2025-07-15.

Una alternativa más eficiente que permite el uso de índices es comparar con un rango.

SELECT id, producto_id, cantidad, precio_unitario
FROM ventas
WHERE fecha_venta >= CURDATE()
  AND fecha_venta < CURDATE() + INTERVAL 1 DAY;

Esta forma evita aplicar la función DATE() sobre la columna, lo que permite a MySQL aprovechar un índice en fecha_venta para la búsqueda.

Caso práctico: calcular edades y antigüedades

CURDATE() es la función ideal para calcular la edad de una persona o la antigüedad de un empleado, porque estas medidas se expresan en días completos sin importar la hora.

CREATE TABLE empleados (
    id INT AUTO_INCREMENT PRIMARY KEY,
    nombre VARCHAR(100) NOT NULL,
    fecha_nacimiento DATE NOT NULL,
    fecha_contratacion DATE NOT NULL,
    departamento VARCHAR(50) NOT NULL
);
 
SELECT nombre, fecha_nacimiento,
       TIMESTAMPDIFF(YEAR, fecha_nacimiento, CURDATE()) AS edad,
       TIMESTAMPDIFF(YEAR, fecha_contratacion, CURDATE()) AS anios_empresa
FROM empleados
ORDER BY edad DESC;
nombrefecha_nacimientoedadanios_empresa
María González1978-03-124715
Carlos Ruiz1985-11-28398
Ana Martínez1990-06-05355
Pedro Sánchez1995-01-17302

TIMESTAMPDIFF con CURDATE() calcula los años completos transcurridos. Si usaras NOW() en lugar de CURDATE(), el resultado sería el mismo porque TIMESTAMPDIFF con unidad YEAR solo cuenta años completos, pero CURDATE() comunica mejor la intención de que la hora es irrelevante.

Caso práctico: comparaciones relativas de fecha

Puedes combinar CURDATE() con INTERVAL para definir rangos de fechas relativos al día actual, lo que es útil en reportes recurrentes.

SELECT nombre, fecha_contratacion
FROM empleados
WHERE fecha_contratacion >= CURDATE() - INTERVAL 90 DAY
ORDER BY fecha_contratacion DESC;
nombrefecha_contratacion
Pedro Sánchez2025-05-20

Para encontrar empleados cuyo cumpleaños es hoy, puedes comparar el mes y día con los de CURDATE().

SELECT nombre, fecha_nacimiento
FROM empleados
WHERE MONTH(fecha_nacimiento) = MONTH(CURDATE())
  AND DAY(fecha_nacimiento) = DAY(CURDATE());

También puedes calcular cuántos días faltan para una fecha límite.

SELECT id, producto_id,
       DATEDIFF('2025-07-31', CURDATE()) AS dias_restantes
FROM ventas
WHERE DATE(fecha_venta) = CURDATE();
idproducto_iddias_restantes
4121516
413816
4142216

Manejo de NULL

CURDATE() nunca devuelve NULL. Siempre produce la fecha actual del servidor. Sin embargo, al compararla con columnas que pueden contener NULL, debes considerar que cualquier comparación con NULL produce NULL (no TRUE ni FALSE).

SELECT nombre, fecha_contratacion,
       DATEDIFF(CURDATE(), fecha_contratacion) AS dias_en_empresa
FROM empleados;

Si fecha_contratacion fuera NULL para algún empleado, DATEDIFF devolvería NULL para esa fila. En estos casos, usa COALESCE para proporcionar un valor de respaldo.

SELECT nombre,
       DATEDIFF(CURDATE(), COALESCE(fecha_contratacion, CURDATE())) AS dias_en_empresa
FROM empleados;

Combinación con otras funciones

CURDATE() se integra naturalmente con funciones de formato y extracción de componentes.

SELECT CURDATE() AS fecha,
       DAYNAME(CURDATE()) AS dia_semana,
       DAYOFYEAR(CURDATE()) AS dia_del_anio,
       WEEK(CURDATE()) AS semana,
       QUARTER(CURDATE()) AS trimestre,
       DATE_FORMAT(CURDATE(), '%d de %M de %Y') AS formato_largo;
fechadia_semanadia_del_aniosemanatrimestreformato_largo
2025-07-15Tuesday19628315 de July de 2025

Para obtener el primer y último día del mes actual, combina CURDATE() con funciones de fecha.

SELECT CURDATE() AS hoy,
       DATE_FORMAT(CURDATE(), '%Y-%m-01') AS primer_dia_mes,
       LAST_DAY(CURDATE()) AS ultimo_dia_mes;
hoyprimer_dia_mesultimo_dia_mes
2025-07-152025-07-012025-07-31

Estas combinaciones son la base de muchos reportes mensuales y semanales en aplicaciones de negocio.

En el siguiente artículo veremos CURTIME para obtener solo la hora actual.

Escrito por Eduardo Lázaro