Las fechas y horas son uno de los tipos de datos más habituales en bases de datos: pedidos, registros de usuarios, logs de acceso, tareas programadas... casi todo tiene una dimensión temporal. MySQL ofrece un conjunto amplio de funciones para obtener, formatear y calcular con fechas directamente en SQL.
En este capítulo cubrimos las funciones más usadas: obtener la fecha y hora actual, extraer partes de una fecha, calcular diferencias y formatear para mostrar al usuario.
Obtener la fecha y hora actuales
-- Fecha y hora actual (según el servidor) SELECT NOW(); -- '2026-05-09 18:00:00' SELECT CURRENT_TIMESTAMP; -- idéntico a NOW() -- Solo fecha SELECT CURDATE(); -- '2026-05-09' SELECT CURRENT_DATE; -- idéntico a CURDATE() -- Solo hora SELECT CURTIME(); -- '18:00:00' SELECT CURRENT_TIME; -- idéntico a CURTIME() -- Marca de tiempo Unix (segundos desde 1970-01-01) SELECT UNIX_TIMESTAMP(); -- número entero SELECT FROM_UNIXTIME(1715270400); -- convierte de Unix a DATETIME
Extraer partes de una fecha
-- Funciones individuales
SELECT YEAR('2026-05-09'); -- 2026
SELECT MONTH('2026-05-09'); -- 5
SELECT DAY('2026-05-09'); -- 9
SELECT HOUR('18:30:45'); -- 18
SELECT MINUTE('18:30:45'); -- 30
SELECT SECOND('18:30:45'); -- 45
-- EXTRACT: más estándar (funciona en MySQL y PostgreSQL)
SELECT EXTRACT(YEAR FROM '2026-05-09'); -- 2026
SELECT EXTRACT(MONTH FROM fecha_alta) AS mes FROM clientes;
-- Día de la semana (1=Domingo, 7=Sábado en MySQL)
SELECT DAYOFWEEK('2026-05-09'); -- 7 (sábado)
-- WEEKDAY: 0=Lunes, 6=Domingo
SELECT WEEKDAY('2026-05-09'); -- 5 (sábado)
-- Número de semana del año
SELECT WEEK('2026-05-09'); -- 18
SELECT DAYOFYEAR('2026-05-09'); -- 129
Calcular diferencias entre fechas
-- DATEDIFF: diferencia en días (fecha1 - fecha2)
SELECT DATEDIFF('2026-05-09', '2024-01-01'); -- días transcurridos
SELECT DATEDIFF(CURDATE(), fecha_alta) AS dias_desde_alta FROM clientes;
-- TIMESTAMPDIFF: diferencia en la unidad que elijas
SELECT TIMESTAMPDIFF(YEAR, '1990-06-15', CURDATE()) AS edad;
SELECT TIMESTAMPDIFF(MONTH, '2024-01-01', CURDATE()) AS meses;
SELECT TIMESTAMPDIFF(DAY, '2024-01-01', CURDATE()) AS dias;
-- Ejemplo: clientes que llevan más de un año registrados
SELECT nombre, fecha_alta
FROM clientes
WHERE TIMESTAMPDIFF(YEAR, fecha_alta, CURDATE()) >= 1;
Sumar y restar intervalos
-- DATE_ADD / DATE_SUB
SELECT DATE_ADD(CURDATE(), INTERVAL 30 DAY); -- dentro de 30 días
SELECT DATE_ADD(CURDATE(), INTERVAL 3 MONTH); -- dentro de 3 meses
SELECT DATE_ADD(CURDATE(), INTERVAL 1 YEAR); -- dentro de un año
SELECT DATE_SUB('2026-05-09', INTERVAL 7 DAY); -- hace 7 días
-- Con horas y minutos
SELECT DATE_ADD(NOW(), INTERVAL '1:30' HOUR_MINUTE);
-- Operador + INTERVAL (equivalente, más legible)
SELECT '2026-01-01' + INTERVAL 100 DAY; -- 2026-04-11
-- Ejemplo: pedidos de las últimas 48 horas
SELECT id, fecha, total FROM pedidos
WHERE fecha >= NOW() - INTERVAL 48 HOUR;
Formatear fechas para mostrar al usuario
-- DATE_FORMAT: equivalente a strftime() de C / date() de PHP
SELECT DATE_FORMAT(fecha_alta, '%d/%m/%Y') AS fecha_es FROM clientes;
-- '15/01/2023'
SELECT DATE_FORMAT(fecha_alta, '%d de %M de %Y') AS fecha_larga FROM clientes;
-- '15 de January de 2023' (nombres de meses en inglés en MySQL)
-- Para nombres en español, mapear el número de mes con CASE o ELT():
SELECT
nombre,
CONCAT(
DAY(fecha_alta), ' de ',
ELT(MONTH(fecha_alta),
'enero','febrero','marzo','abril','mayo','junio',
'julio','agosto','septiembre','octubre','noviembre','diciembre'),
' de ', YEAR(fecha_alta)
) AS fecha_castellano
FROM clientes;
Comparar fechas en WHERE
-- Pedidos de hoy SELECT * FROM pedidos WHERE DATE(fecha) = CURDATE(); -- Pedidos del mes actual SELECT * FROM pedidos WHERE YEAR(fecha) = YEAR(CURDATE()) AND MONTH(fecha) = MONTH(CURDATE()); -- Nota: aplicar funciones sobre la columna indexada (como YEAR(fecha)) -- impide usar el índice. Mejor comprar con un rango: SELECT * FROM pedidos WHERE fecha >= DATE_FORMAT(CURDATE(), '%Y-%m-01') AND fecha < DATE_FORMAT(CURDATE(), '%Y-%m-01') + INTERVAL 1 MONTH;
