date_timezone_set()
Aprende cómo date_timezone_set() de PHP convierte un objeto DateTime a otra zona horaria sin cambiar el instante. Sintaxis, horario de verano y ejemplos.
Introducción
date_timezone_set() cambia la zona horaria de un objeto DateTime existente. De forma fundamental, no cambia el instante subyacente en el tiempo — cambia la representación en el reloj de ese instante. El mismo momento simplemente se expresa en una zona horaria diferente, por lo que las horas y minutos mostrados varían mientras el punto absoluto en la línea de tiempo permanece idéntico.
Esto lo convierte en la herramienta adecuada cuando tienes una fecha/hora en una zona y necesitas mostrarla en otra: convertir una marca de tiempo UTC almacenada a la hora local de un usuario, o comparar eventos registrados en diferentes regiones.
date_timezone_set() es el alias procedimental del método DateTime::setTimezone() — ambos hacen exactamente lo mismo.
Sintaxis
date_timezone_set(DateTime $object, DateTimeZone $timezone): DateTime|false$object— el objetoDateTimecuya zona horaria deseas cambiar.$timezone— un objetoDateTimeZoneque contiene la zona de destino (por ejemplonew DateTimeZone('Asia/Tokyo')).
La función muta $object en su lugar y devuelve la misma instancia si tiene éxito (útil para encadenar llamadas), o false en caso de error. Como modifica el objeto original, no existe una "copia" separada — el propio objeto de entrada cambia.
Ejemplo básico
2023-03-03 21:00:00El objeto comienza a las 12:00 en Londres (Europe/London, que es UTC+0 en marzo). Tokio está 9 horas por delante, así que el mismo instante se muestra como 21:00. Nada del momento real cambió — solo la zona en la que se muestra.
El instante permanece igual — solo cambia la representación
Este es el punto más importante para entender date_timezone_set(). Compara el valor antes y después de la conversión:
<?php
$date = new DateTime('2023-03-03 12:00:00', new DateTimeZone('Europe/London'));
echo $date->format('Y-m-d H:i:s P'), "\n"; // before
date_timezone_set($date, new DateTimeZone('Asia/Tokyo'));
echo $date->format('Y-m-d H:i:s P'), "\n"; // after2023-03-03 12:00:00 +00:00
2023-03-03 21:00:00 +09:00La hora en el reloj y el desplazamiento UTC cambian ambos, pero 12:00 +00:00 y 21:00 +09:00 son el mismo punto en el tiempo. Si solo necesitas el instante absoluto (por ejemplo, una marca de tiempo UNIX), no habrá ningún cambio.
Si en cambio deseas reemplazar la hora del reloj sin convertirla, no uses esta función — establece la hora directamente con
date_time_set().
El horario de verano se gestiona automáticamente
Dado que la conversión pasa por un DateTimeZone real, las reglas del horario de verano (DST) se aplican automáticamente. Nueva York es UTC-5 en invierno pero UTC-4 en verano, y date_timezone_set() elige el desplazamiento correcto para la fecha en cuestión:
<?php
$utc = new DateTime('2023-06-21 12:00:00', new DateTimeZone('UTC'));
date_timezone_set($utc, new DateTimeZone('America/New_York'));
echo $utc->format('Y-m-d H:i:s');2023-06-21 08:00:00En junio, Nueva York está en Eastern Daylight Time (UTC-4), por lo que 12:00 UTC se convierte en 08:00. Ejecuta el mismo código con una fecha de enero y obtendrías 07:00 (UTC-5) en su lugar — sin ningún cambio en el código. Por eso siempre debes usar identificadores de zona IANA como America/New_York en lugar de desplazamientos fijos como -05:00.
Estilo procedimental vs. orientado a objetos
date_timezone_set($obj, $tz) y $obj->setTimezone($tz) son intercambiables. La forma de método generalmente resulta más legible y se encadena de forma natural:
<?php
$london = (new DateTime('2023-03-03 12:00:00', new DateTimeZone('Europe/London')))
->setTimezone(new DateTimeZone('Asia/Tokyo'));
echo $london->format('Y-m-d H:i:s');2023-03-03 21:00:00Casos de uso habituales
- Mostrar marcas de tiempo UTC almacenadas en la zona de un usuario. Almacena cada marca de tiempo en UTC y luego conviértela al mostrarla con
date_timezone_set()para la zona horaria preferida de cada usuario. - Normalizar horas de múltiples regiones antes de compararlas u ordenarlas.
- Generar informes con conciencia regional, mostrando el mismo evento en varias zonas de forma simultánea.
Aspectos a tener en cuenta
- Muta el objeto original. Si necesitas conservar el valor fuente, clónalo primero:
$copy = clone $date;y luego convierte$copy. - No analiza ni establece una nueva fecha — solo reproyecta el instante existente. Usa
date_create()para crear unDateTimeydate_time_set()para sobrescribir la hora. - Para leer la zona actualmente asociada a un objeto, usa
date_timezone_get(). - No lo confundas con
date_default_timezone_set(), que establece la zona predeterminada a nivel de script para todas las funciones de fecha/hora — una tarea completamente diferente.
Diagrama
graph LR
A[DateTime Object] --> B((date_timezone_set))
C[Target DateTimeZone] --> B
B --> D[Same instant, new wall-clock display]