Campos de tipo fecha en mysql: guía completa
Los tipos de datos de fecha y hora son fundamentales en casi cualquier base de datos. En MySQL existen varios tipos específicos para manejar fechas, horas y combinaciones de ambas. Elegir el correcto puede ahorrar muchos problemas de almacenamiento, rendimiento y manejo de zonas horarias.Tipos de datos de fecha y hora en MySQL
| Formato | Formato | Rango aproximado | Tamaño de almacenamiento | Observaciones importantes |
|---|---|---|---|---|
| "DATE" | YYYY-MM-DD | 1000-01-01 a 9999-12-31 | 3 bytes | Solo fecha, sin hora |
| "TIME" | HH:MM:SS | -838:59:59 a 838:59:59 | 3 bytes | Solo hora (puede ser mayor a 24h) |
| "DATETIME" | YYYY-MM-DD HH:MM:SS | 1000-01-01 00:00:00 a 9999-12-31 | 5 bytes (hasta 8 con fracciones) | Fecha + hora, sin zona horaria |
| "TIMESTAMP" | YYYY-MM-DD HH:MM:SS | 1970-01-01 a 2038-01-19 | 4 bytes (hasta 7 con fracciones) | Se convierte a UTC automáticamente |
| "YEAR" | YYYY o YY | 1901 a 2155 | 1 byte | Solo el año |
Diferencias clave entre DATETIME y TIMESTAMP
DATETIME
- Guarda exactamente el valor que se le introduce.
- No se ve afectado por la zona horaria del servidor.
- Rango mucho más amplio, hasta el año 9999.
- Ideal para fechas históricas o futuras lejanas, fechas de nacimiento, vencimientos lejanos, etc.
TIMESTAMP
- Internamente se almacena en UTC.
- Al insertar y al consultar se convierte automáticamente según la zona horaria de la sesión.
- Ideal para registrar “cuándo ocurrió algo”, como "created_at", "updated_at".
- Tiene límite del año 2038. aunque con MySQL 8.0.28+ se puede ampliar.
Recomendación práctica
- Usar TIMESTAMP para campos de auditoría”, como "created_at", "updated_at".
- Usar DATETIME cuando la fecha deba ser independiente de la zona horaria.
Ejemplos de uso
Crear una tabla con diferentes tipos de fecha
CREATE TABLE eventos (
id INT AUTO_INCREMENT PRIMARY KEY,
nombre VARCHAR(100),
fecha_evento DATE, -- Solo fecha
hora_inicio TIME, -- Solo hora
fecha_hora_inicio DATETIME, -- Fecha + hora
creado_en TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
actualizado_en TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
anio YEAR
);
Insertar datos
INSERT INTO eventos (nombre, fecha_evento, hora_inicio, fecha_hora_inicio, anio)
VALUES
('Concierto', '2026-10-15', '20:30:00', '2026-10-15 20:30:00', 2026),
('Reunión', '2026-11-01', '09:00:00', '2026-11-01 09:00:00', 2026);
Consultas útiles
-- Eventos de un mes específico
SELECT * FROM eventos
WHERE MONTH(fecha_evento) = 10 AND YEAR(fecha_evento) = 2026;
-- Eventos entre dos fechas
SELECT * FROM eventos
WHERE fecha_hora_inicio BETWEEN '2026-10-01' AND '2026-10-31 23:59:59';
-- Diferencia de días
SELECT nombre, DATEDIFF(fecha_evento, CURDATE()) AS dias_restantes
FROM eventos;
-- Formatear fecha
SELECT nombre, DATE_FORMAT(fecha_hora_inicio, '%d/%m/%Y %H:%i') AS fecha_formateada
FROM eventos;
Funciones más usadas con fechas
- "NOW()" / "CURRENT_TIMESTAMP" → Fecha y hora actual.
- "CURDATE()" → Solo fecha actual.
- "CURTIME()" → Solo hora actual.
- "DATE_ADD()" / "DATE_SUB()" → Sumar o restar intervalos.
- "DATEDIFF()" → Diferencia en días.
- "TIMESTAMPDIFF()" → Diferencia en cualquier unidad, como SECOND, MINUTE, HOUR, DAY, etc..
- "DATE_FORMAT()" → Formatear la salida.
- "STR_TO_DATE()" → Convertir string a fecha.
Buenas prácticas
- Usar siempre el tipo más pequeño posible → Ahorra espacio y mejora el rendimiento.
- Evitar guardar fechas como VARCHAR o INT → Pierde validación y funciones de fecha.
- Usar DEFAULT CURRENT_TIMESTAMP y ON UPDATE CURRENT_TIMESTAMP para campos de auditoría.
- Ten cuidado con las zonas horarias → Configurar time_zone correctamente en el servidor o en la conexión.
- Para rangos grandes de fechas, antes de 1970 o después de 2038 → usar DATETIME.
- Indexar los campos de fecha que uses frecuentemente en filtros, WHERE, ORDER BY, BETWEEN.
Errores comunes
- Insertar fechas en formato incorrecto, como "DD/MM/YYYY" en lugar de "YYYY-MM-DD".
- Confundir TIMESTAMP con DATETIME y tener problemas de zona horaria.
- Usar YEAR cuando realmente necesitas una fecha completa.
- No manejar los valores "NULL" o fechas inválidas, "0000-00-00" está deshabilitado por defecto desde MySQL 5.7+.
CREATE TABLE eventos (
id INT AUTO_INCREMENT PRIMARY KEY,
nombre VARCHAR(100),
fecha_evento DATE, -- Solo fecha
hora_inicio TIME, -- Solo hora
fecha_hora_inicio DATETIME, -- Fecha + hora
creado_en TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
actualizado_en TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
anio YEAR
);
INSERT INTO eventos (nombre, fecha_evento, hora_inicio, fecha_hora_inicio, anio)
VALUES
('Concierto', '2026-10-15', '20:30:00', '2026-10-15 20:30:00', 2026),
('Reunión', '2026-11-01', '09:00:00', '2026-11-01 09:00:00', 2026);
-- Eventos de un mes específico
SELECT * FROM eventos
WHERE MONTH(fecha_evento) = 10 AND YEAR(fecha_evento) = 2026;
-- Eventos entre dos fechas
SELECT * FROM eventos
WHERE fecha_hora_inicio BETWEEN '2026-10-01' AND '2026-10-31 23:59:59';
-- Diferencia de días
SELECT nombre, DATEDIFF(fecha_evento, CURDATE()) AS dias_restantes
FROM eventos;
-- Formatear fecha
SELECT nombre, DATE_FORMAT(fecha_hora_inicio, '%d/%m/%Y %H:%i') AS fecha_formateada
FROM eventos;
- "NOW()" / "CURRENT_TIMESTAMP" → Fecha y hora actual.
- "CURDATE()" → Solo fecha actual.
- "CURTIME()" → Solo hora actual.
- "DATE_ADD()" / "DATE_SUB()" → Sumar o restar intervalos.
- "DATEDIFF()" → Diferencia en días.
- "TIMESTAMPDIFF()" → Diferencia en cualquier unidad, como SECOND, MINUTE, HOUR, DAY, etc..
- "DATE_FORMAT()" → Formatear la salida.
- "STR_TO_DATE()" → Convertir string a fecha.