date_timezone_set()
Aprenda como date_timezone_set() converte um objeto DateTime para outro fuso horário sem alterar o instante. Sintaxe, DST e exemplos.
Introdução
date_timezone_set() altera o fuso horário de um object DateTime existente. De forma importante, ela não altera o instante subjacente no tempo — ela muda a representação no relógio de parede desse instante. O mesmo momento é simplesmente reexpresso em um fuso horário diferente, de modo que as horas e minutos exibidos mudam enquanto o ponto absoluto na linha do tempo permanece idêntico.
Isso torna a função a ferramenta certa sempre que você tem uma data/hora em um fuso e precisa exibi-la em outro: convertendo um timestamp UTC armazenado para a hora local do usuário, ou comparando eventos registrados em diferentes regiões.
date_timezone_set() é o alias procedural do método DateTime::setTimezone() — ambos fazem exatamente a mesma coisa.
Sintaxe
date_timezone_set(DateTime $object, DateTimeZone $timezone): DateTime|false$object— o objectDateTimecujo fuso horário você deseja alterar.$timezone— um objectDateTimeZoneque contém o fuso de destino (por exemplo,new DateTimeZone('Asia/Tokyo')).
A função muta $object in place e retorna a mesma instância em caso de sucesso (útil para encadeamento), ou false em caso de falha. Como ela modifica o object original, não há uma "cópia" separada — o próprio object de entrada é alterado.
Exemplo básico
2023-03-03 21:00:00O object começa às 12:00 em Londres (Europe/London, que é UTC+0 em março). Tóquio está 9 horas à frente, então o mesmo instante é exibido como 21:00. Nada sobre o momento real mudou — apenas o fuso em que ele é mostrado.
O instante permanece o mesmo — apenas a exibição muda
Este é o ponto mais importante para entender sobre date_timezone_set(). Compare o valor antes e depois da conversão:
<?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:00O horário no relógio de parede e o offset UTC mudam, mas 12:00 +00:00 e 21:00 +09:00 são o mesmo ponto no tempo. Se você precisa apenas do instante absoluto (por exemplo, um timestamp UNIX), ele permanecerá inalterado.
Se você quiser substituir o horário no relógio de parede sem convertê-lo, não use esta função — defina o horário diretamente com
date_time_set().
O horário de verão é tratado automaticamente
Como a conversão passa por um DateTimeZone real, as regras de horário de verão (DST) são aplicadas automaticamente. Nova York é UTC-5 no inverno, mas UTC-4 no verão, e date_timezone_set() escolhe o offset correto para a data em questão:
<?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:00Em junho, Nova York está no horário de verão do leste (UTC-4), então 12:00 UTC se torna 08:00. Execute o mesmo código com uma data de janeiro e você obteria 07:00 (UTC-5) — sem qualquer alteração no seu código. É por isso que você deve sempre usar identificadores de fuso IANA como America/New_York em vez de offsets fixos como -05:00.
Estilo procedural vs. orientado a objetos
date_timezone_set($obj, $tz) e $obj->setTimezone($tz) são intercambiáveis. A forma de método geralmente é mais legível e encadeia naturalmente:
<?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 comuns
- Exibir timestamps UTC armazenados no fuso do usuário. Armazene todos os timestamps em UTC e converta na saída com
date_timezone_set()para o fuso preferido de cada usuário. - Normalizar horários de múltiplas regiões antes de compará-los ou ordená-los.
- Criar relatórios com consciência regional, mostrando o mesmo evento em vários fusos lado a lado.
Pontos de atenção
- Ela muta o object original. Se você precisar manter o valor original, clone-o primeiro:
$copy = clone $date;e então converta$copy. - Ela não analisa nem define uma nova data — ela apenas reprojecta o instante existente. Use
date_create()para construir umDateTimeedate_time_set()para sobrescrever o horário. - Para ler o fuso atualmente associado a um object, use
date_timezone_get(). - Não a confunda com
date_default_timezone_set(), que define o fuso padrão do script para todas as funções de data/hora — uma tarefa completamente diferente.
Diagrama
graph LR
A[DateTime Object] --> B((date_timezone_set))
C[Target DateTimeZone] --> B
B --> D[Same instant, new wall-clock display]