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;
idusuarioipinicioultima_actividad
1maria192.168.1.102026-02-14 14:30:002026-02-14 14:30:00
2carlos10.0.0.52026-02-14 14:30:002026-02-14 14:30:00
3ana172.16.0.202026-02-14 14:30:002026-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;
columnatabladefecto
fecha_registroclientesCURRENT_TIMESTAMP
creado_enproductosCURRENT_TIMESTAMP
actualizado_enproductosCURRENT_TIMESTAMP
fecharesenasCURRENT_TIMESTAMP

Veamos las fechas de registro de los clientes:

SELECT nombre, ciudad, fecha_registro
FROM clientes
ORDER BY fecha_registro
LIMIT 5;
nombreciudadfecha_registro
MaríaMadrid2025-10-01 10:00:00
CarlosBarcelona2025-10-01 10:00:00
AnaSevilla2025-10-01 10:00:00
PedroMadrid2025-10-01 10:00:00
LauraBarcelona2025-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;
idtextocreado_en
1Primer comentario2026-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;
idusuarioipinicioultima_actividad
1maria192.168.1.112026-02-14 14:30:002026-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ísticaTIMESTAMPDATETIME
Almacenamiento4 bytes5 bytes
Rango1970-20381000-9999
Zona horariaConvierte a/desde UTCSin conversión
NULL por defectoNOT NULL (históricamente)Permite NULL
Uso idealAuditoría, logsEventos, 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;
eventots
click2026-02-14 14:30:00.123
scroll2026-02-14 14:30:00.456
submit2026-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;
ahoraepochdesde_epoch
2026-02-14 14:30:0017710794002025-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