DateTime vs Timestamp en Laravel: cuál usar y por qué
Diferencias entre DateTime y Timestamp en Laravel, el problema del año 2038, por qué guardar en UTC y cómo convertir timezones con Carbon sin romper nada.
Introducción
Laravel hace fácil el manejo de fechas, pero elegir mal el tipo de columna o la estrategia de timezone te trae problemas de integridad de datos más adelante. Mucha gente busca la diferencia entre DateTime y Timestamp en Laravel, y la clave real está en cómo guardás y cómo mostrás ese dato. En esta guía comparo los dos tipos, explico la limitación del "año 2038" y vemos las conversiones a UTC.
DateTime o Timestamp en Laravel: ¿cuál conviene?
Cuando escribís migraciones elegís entre $table->timestamp() y $table->dateTime(). Este es el desglose técnico
| Característica | Timestamp | DateTime |
|---|---|---|
| Rango en MySQL | 1970-01-01 to 2038-01-19 | 0001-01-01 to 9999-12-31 |
| Tamaño | 4 bytes | 8 bytes |
| Manejo de TZ | Convierte a UTC al guardar | Guarda el valor literal (ignora el offset) |
| Default de Laravel | Lo usa $table->timestamps() | Hay que definirlo a mano |
El problema del "año 2038"
Una diferencia crítica es que los Timestamps se guardan como un entero de 32 bits que representa los segundos desde el Unix Epoch. O sea que van a desbordar el 19 de enero de 2038. Si tu aplicación maneja fechas lejanas, como hipotecas a 30 años o fechas de nacimiento, usá columnas DateTime para esquivar ese límite.
Por qué Laravel recomienda UTC (pero no te obliga)
Se cree que Laravel siempre guarda los timestamps en UTC, y no es así. Laravel guarda con la timezone que hayas puesto en config/app.php. Si tu app está en America/New_York, entonces created_at se guarda en hora del Este.
Buena práctica: poné siempre la timezone de la aplicación en UTC. Guardar en UTC te evita los saltos de horario de verano y te ordena las integraciones con servicios como Stripe, Twilio y AWS.
Cómo maneja Laravel las timezones con Carbon
Laravel no asume que tu base está en UTC. Lee el valor crudo y lo envuelve en una instancia de Carbon, usando la timezone que definiste en el config.
// config/app.php
'timezone' => 'UTC';
$post = Post::find(1);
// Even if stored as a 'datetime' column, Carbon treats it as UTC
echo $post->created_at->timezone; // "UTC"
Mientras el config sea consistente, Carbon hace las conversiones claras y predecibles en todo el codebase.
Integración con el ecosistema de Laravel
Guardar los timestamps en UTC encaja perfecto con el ecosistema de Laravel y con los paquetes de terceros:
- Jobs en cola de Laravel: los jobs programados usan timestamps UTC para el dispatch diferido
- Notificaciones de Laravel: los timestamps de las notificaciones se comparan en UTC
- APIs de terceros: la mayoría de los servicios (Stripe, Twilio, AWS) devuelven timestamps en UTC
- Laravel Horizon: las métricas y los tiempos de los jobs van todos en UTC
- Laravel Telescope: los timestamps de los requests se registran en UTC
Estrategias para convertir timezones
Una vez que el dato está guardado en UTC, tenés que mostrárselo al usuario en su hora local.
Conversión en el cliente (recomendado)
Lo más simple es mandar el string UTC en ISO-8601 al frontend y dejar que JavaScript, o el frontend que uses, se encargue del resto.
// The 'Z' denotes UTC
let utcTimestamp = "2024-08-23T12:00:00Z";
let localDate = new Date(utcTimestamp);
console.log(localDate.toLocaleString());
- Pros: detecta automáticamente la timezone local del usuario.
- Contras: puede generar un parpadeo al cargar la página si no lo resolvés con SSR.
2. Conversión en el servidor
Si guardás la timezone preferida del usuario en la tabla users, podés convertirla antes de que el dato llegue a la vista.
$userTimezone = auth()->user()->timezone; // e.g., 'Europe/Madrid'
$converted = $post->created_at->setTimezone($userTimezone);
3. Manejar el horario de verano (DST)
Un aspecto complicado de las timezones es el DST. Por suerte, Carbon y los objetos Date modernos de JavaScript lo manejan solos. Eso sí: usá strings basados en ubicación (como America/New_York) en lugar de offsets fijos (como -05:00).
Conclusión
La discusión DateTime vs Timestamp en Laravel suele terminar en el rango de almacenamiento, pero lo que de verdad importa es aplicar un workflow estricto: guardar en UTC, mostrar en local. Resolverlo ahora te ahorra dolores de cabeza enormes cuando la aplicación crezca a otros países.
¡A codear!
¿Necesitás ayuda con una base de código Laravel o un desarrollo como este? Mirá mi servicio de consultoría Laravel.