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_fecha | fecha_y_hora |
|---|---|
| 2025-07-15 | 2025-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_1 | forma_2 | forma_3 |
|---|---|---|
| 2025-07-15 | 2025-07-15 | 2025-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;| id | producto_id | cantidad | precio_unitario | subtotal |
|---|---|---|---|---|
| 412 | 15 | 2 | 49.90 | 99.80 |
| 413 | 8 | 1 | 189.00 | 189.00 |
| 414 | 22 | 5 | 12.50 | 62.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;| nombre | fecha_nacimiento | edad | anios_empresa |
|---|---|---|---|
| María González | 1978-03-12 | 47 | 15 |
| Carlos Ruiz | 1985-11-28 | 39 | 8 |
| Ana Martínez | 1990-06-05 | 35 | 5 |
| Pedro Sánchez | 1995-01-17 | 30 | 2 |
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;| nombre | fecha_contratacion |
|---|---|
| Pedro Sánchez | 2025-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();| id | producto_id | dias_restantes |
|---|---|---|
| 412 | 15 | 16 |
| 413 | 8 | 16 |
| 414 | 22 | 16 |
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;| fecha | dia_semana | dia_del_anio | semana | trimestre | formato_largo |
|---|---|---|---|---|---|
| 2025-07-15 | Tuesday | 196 | 28 | 3 | 15 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;| hoy | primer_dia_mes | ultimo_dia_mes |
|---|---|---|
| 2025-07-15 | 2025-07-01 | 2025-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
