TIMESTAMP
TIMESTAMP almacena fecha y hora con conversión automática de zona horaria. Al insertar un valor, MySQL lo convierte de la zona horaria de la sesión a UTC para almacenarlo. Al leerlo, lo convierte de UTC a la zona horaria de la sesión. Esto garantiza que los valores sean correctos independientemente de la zona horaria del usuario. Ocupa 4 bytes y tiene un rango desde 1970-01-01 00:00:01 UTC hasta 2038-01-19 03:14:07 UTC.
Sintaxis
CREATE TABLE nombre_tabla (
creado_en TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
actualizado_en TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);Ejemplo básico
CREATE TABLE sesiones (
id INT AUTO_INCREMENT PRIMARY KEY,
usuario VARCHAR(50) NOT NULL,
ip VARCHAR(45),
inicio TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
ultima_actividad TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);
INSERT INTO sesiones (usuario, ip) VALUES
('maria', '192.168.1.10'),
('carlos', '10.0.0.5'),
('ana', '172.16.0.20');
SELECT * FROM sesiones;| id | usuario | ip | inicio | ultima_actividad |
|---|---|---|---|---|
| 1 | maria | 192.168.1.10 | 2026-02-14 14:30:00 | 2026-02-14 14:30:00 |
| 2 | carlos | 10.0.0.5 | 2026-02-14 14:30:00 | 2026-02-14 14:30:00 |
| 3 | ana | 172.16.0.20 | 2026-02-14 14:30:00 | 2026-02-14 14:30:00 |
CURRENT_TIMESTAMP establece la fecha y hora actuales automáticamente al insertar. ON UPDATE CURRENT_TIMESTAMP actualiza la columna automáticamente cada vez que la fila se modifica.
TIMESTAMP en tienda_mysql
La base de datos usa TIMESTAMP en varias tablas para auditoría:
SELECT COLUMN_NAME AS columna, TABLE_NAME AS tabla, COLUMN_DEFAULT AS defecto
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = 'tienda_mysql'
AND DATA_TYPE = 'timestamp'
ORDER BY TABLE_NAME;| columna | tabla | defecto |
|---|---|---|
| fecha_registro | clientes | CURRENT_TIMESTAMP |
| creado_en | productos | CURRENT_TIMESTAMP |
| actualizado_en | productos | CURRENT_TIMESTAMP |
| fecha | resenas | CURRENT_TIMESTAMP |
Veamos las fechas de registro de los clientes:
SELECT nombre, ciudad, fecha_registro
FROM clientes
ORDER BY fecha_registro
LIMIT 5;| nombre | ciudad | fecha_registro |
|---|---|---|
| María | Madrid | 2025-10-01 10:00:00 |
| Carlos | Barcelona | 2025-10-01 10:00:00 |
| Ana | Sevilla | 2025-10-01 10:00:00 |
| Pedro | Madrid | 2025-10-01 10:00:00 |
| Laura | Barcelona | 2025-10-01 10:00:00 |
DEFAULT CURRENT_TIMESTAMP
DEFAULT CURRENT_TIMESTAMP (sinónimos: DEFAULT NOW(), DEFAULT CURRENT_TIMESTAMP()) asigna la fecha y hora actuales al insertar una fila:
CREATE TABLE comentarios (
id INT AUTO_INCREMENT PRIMARY KEY,
texto VARCHAR(500) NOT NULL,
creado_en TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
INSERT INTO comentarios (texto) VALUES ('Primer comentario');
-- No especificamos creado_en, se llena automáticamente
SELECT * FROM comentarios;| id | texto | creado_en |
|---|---|---|
| 1 | Primer comentario | 2026-02-14 14:30:00 |
ON UPDATE CURRENT_TIMESTAMP
Esta cláusula actualiza la columna automáticamente cuando cualquier otra columna de la fila cambia:
UPDATE sesiones SET ip = '192.168.1.11' WHERE id = 1;
SELECT id, usuario, ip, inicio, ultima_actividad FROM sesiones WHERE id = 1;| id | usuario | ip | inicio | ultima_actividad |
|---|---|---|---|---|
| 1 | maria | 192.168.1.11 | 2026-02-14 14:30:00 | 2026-02-14 14:35:00 |
inicio mantiene su valor original. ultima_actividad se actualizó automáticamente a la hora actual.
Conversión de zona horaria
El comportamiento más importante de TIMESTAMP es la conversión automática de zona horaria:
-- Ver la zona horaria actual
SELECT @@session.time_zone AS zona;| zona |
|---|
| SYSTEM |
-- Insertar un valor
CREATE TABLE test_tz (ts TIMESTAMP);
INSERT INTO test_tz VALUES ('2026-02-14 12:00:00');
-- Leer con la zona horaria original
SELECT ts FROM test_tz;| ts |
|---|
| 2026-02-14 12:00:00 |
-- Cambiar la zona horaria de la sesión
SET SESSION time_zone = '+09:00'; -- Tokio
SELECT ts FROM test_tz;| ts |
|---|
| 2026-02-14 20:00:00 |
El mismo registro muestra una hora diferente según la zona horaria de la sesión. Internamente, MySQL almacenó el valor en UTC. Al leerlo con la zona horaria de Tokio (+09:00), suma 9 horas si el original era UTC, o la diferencia correspondiente.
-- Restaurar zona horaria
SET SESSION time_zone = 'SYSTEM';El problema del año 2038
TIMESTAMP almacena internamente el número de segundos desde 1970-01-01 00:00:00 UTC (Unix epoch) como un entero de 32 bits con signo. El valor máximo es 2038-01-19 03:14:07 UTC:
-- Esto funciona
SELECT TIMESTAMP('2038-01-19 03:14:07');| TIMESTAMP('2038-01-19 03:14:07') |
|---|
| 2038-01-19 03:14:07 |
Si necesitas fechas después de 2038, usa DATETIME en lugar de TIMESTAMP.
TIMESTAMP vs DATETIME
| Característica | TIMESTAMP | DATETIME |
|---|---|---|
| Almacenamiento | 4 bytes | 5 bytes |
| Rango | 1970-2038 | 1000-9999 |
| Zona horaria | Convierte a/desde UTC | Sin conversión |
| NULL por defecto | NOT NULL (históricamente) | Permite NULL |
| Uso ideal | Auditoría, logs | Eventos, fechas fijas |
Usa TIMESTAMP para registros de auditoría (cuándo se creó/modificó algo). Usa DATETIME para fechas absolutas que no deben cambiar con la zona horaria (fecha de un evento, cumpleaños).
Múltiples columnas TIMESTAMP
Puedes tener varias columnas TIMESTAMP en una tabla, pero solo una puede tener ON UPDATE CURRENT_TIMESTAMP:
CREATE TABLE auditoria (
id INT AUTO_INCREMENT PRIMARY KEY,
dato VARCHAR(100),
creado_en TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
modificado_en TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
revisado_en TIMESTAMP NULL
);TIMESTAMP con fracciones de segundo
CREATE TABLE metricas (
id INT AUTO_INCREMENT PRIMARY KEY,
evento VARCHAR(50),
ts TIMESTAMP(3) DEFAULT CURRENT_TIMESTAMP(3)
);
INSERT INTO metricas (evento) VALUES ('click'), ('scroll'), ('submit');
SELECT evento, ts FROM metricas;| evento | ts |
|---|---|
| click | 2026-02-14 14:30:00.123 |
| scroll | 2026-02-14 14:30:00.456 |
| submit | 2026-02-14 14:30:00.789 |
TIMESTAMP(3) almacena milisegundos. La precisión va de 0 a 6 (microsegundos).
UNIX_TIMESTAMP y FROM_UNIXTIME
Convierte entre TIMESTAMP y Unix epoch (segundos):
SELECT
NOW() AS ahora,
UNIX_TIMESTAMP(NOW()) AS epoch,
FROM_UNIXTIME(1739538600) AS desde_epoch;| ahora | epoch | desde_epoch |
|---|---|---|
| 2026-02-14 14:30:00 | 1771079400 | 2025-02-14 14:30:00 |
UNIX_TIMESTAMP es útil cuando interactúas con APIs que usan timestamps Unix.
Limpieza
DROP TABLE IF EXISTS sesiones;
DROP TABLE IF EXISTS comentarios;
DROP TABLE IF EXISTS test_tz;
DROP TABLE IF EXISTS auditoria;
DROP TABLE IF EXISTS metricas;En el siguiente artículo veremos BLOB, el tipo para almacenar datos binarios como imágenes o archivos.
Escrito por Eduardo Lázaro
