Capítulo 16
Datas e horário do registro
5 min de leitura 840 palavras 1 gravura
Neste capítulo você vai registrar um instante com fuso explícito e apresentá-lo num formato legível.
Seu ponto de partida
Estude depois do capítulo 15. O exemplo deste capítulo é 16-datas-horarios, no pacote que acompanha o volume. Copie a pasta inicio para um diretório de prática e preserve o original. A raiz do exemplo é a referência concluída desta etapa. Sua cópia permite experimentar sem perder a referência.
Execute o PHP na raiz da sua cópia com php -S 127.0.0.1:8000 -t public. Abra http://127.0.0.1:8000/. Não abra PHP por duplo clique nem use o servidor de Python. Encerre com Ctrl+C antes de trocar de etapa.
Como praticar
Leia a explicação e digite ou confira o código indicado. Mude uma coisa. Antes de conferir, anote sua previsão. Salve, recarregue e compare. Se não acontecer o esperado, investigue o erro antes de avançar. Cada experiência parte dos valores da referência. Depois de conferir, desfaça somente a mudança desse experimento antes de começar a próxima lição. Você pode parar depois de uma lição e retomar mais tarde.
Um instante precisa de contexto
Date formata uma data segundo o fuso configurado no PHP. Um fuso define como representar o horário de um instante numa região. A referência usa DateTimeImmutable com DateTimeZone, mantendo o fuso explícito na própria tarefa.
O valor fictício está fixado para a experiência ser repetível. Não use seu relógio como resposta de uma atividade que precisa de resultado conhecido. No livro de visitas, a gravação registra o horário real do envio.
Faça no seu exemplo
Em public/index.php, localize o bloco indicado. A referência completa acompanha esta etapa.
$fuso = new DateTimeZone("America/Recife");
$instante = new DateTimeImmutable("2026-09-14 10:30:00", $fuso);
Mude uma coisa e preveja
Troque somente 10:30:00 por 11:30:00.
Anote o que você acha que vai acontecer antes de salvar e recarregar.
Recarregue e confira
O horário apresentado muda uma hora.
Se não acontecer
Se a data ficar inesperada, restaure o texto completo e confira ano-mês-dia. Não misture o formato de entrada com dia/mês/ano.
Guarde uma forma e mostre outra
Formatar uma data muda sua representação; não muda o instante guardado. O formato c inclui data, horário e deslocamento do fuso. É útil para o registro. D/m/Y H:i organiza a apresentação para leitura.
No formato do PHP, m representa mês e i representa minutos. Letras maiúsculas e minúsculas podem ter significados diferentes. Compare com a referência em vez de decorar tudo.
Faça no seu exemplo
Em public/index.php, localize o bloco indicado. A referência completa acompanha esta etapa.
$registro = $instante->format("c");
$legivel = $instante->format("d/m/Y H:i");
Mude uma coisa e preveja
Troque somente H:i por H no formato legível.
Anote o que você acha que vai acontecer antes de salvar e recarregar.
Recarregue e confira
A apresentação deixa de mostrar os minutos; o registro completo permanece igual.
Se não acontecer
Se o minuto mostrar o mês, confira i. Usar m naquele lugar pede o mês.
Converta o fuso sem mudar o instante
DateTimeImmutable devolve um novo objeto ao converter o fuso. O original permanece. Nesta etapa, objeto significa um valor que oferece tarefas próprias, chamadas métodos. A seta -> chama uma dessas tarefas. Não é necessário estudar toda a programação orientada a objetos para usar esta operação pequena.
UTC é uma referência de horário. Recife está três horas atrás de UTC no exemplo fixado. Conferimos a conversão pelos dois horários e pelo deslocamento do registro.
Faça no seu exemplo
Em public/index.php, localize o bloco indicado. A referência completa acompanha esta etapa.
$utc = $instante->setTimezone(new DateTimeZone("UTC"));
Mude uma coisa e preveja
Mantenha a hora de entrada 10:30 e compare a saída de Recife com UTC.
Anote o que você acha que vai acontecer antes de salvar e recarregar.
Recarregue e confira
Recife mostra 10:30 e UTC mostra 13:30 para o mesmo instante desta referência.
Se não acontecer
Se ambos mostrarem igual, confira se a segunda saída usa utc em vez de instante. Não adicione três horas manualmente a um valor já convertido.

A captura mostra um trecho da referência concluída. Abra e percorra o exemplo para conferir o restante. Experimentos temporários podem produzir outra aparência; restaure os valores indicados antes de comparar.
Atividades para fazer antes das respostas
Use uma nova cópia do exemplo. Tente aplicar o que aprendeu antes de consultar os comentários.
-
Mude o instante fixo para 09:00.
-
Explique por que usar i para minutos.
-
Compare registro e apresentação legível.
Respostas comentadas
Compare sua explicação e o que realmente aconteceu. Outra solução pode funcionar se cumprir o objetivo e preservar o acesso ao conteúdo.
-
UTC passa a 12:00 no exemplo.
-
O formato do PHP reserva m para mês e i para minutos.
-
Registro inclui fuso e forma estável; apresentação prioriza leitura. Ambos representam o mesmo instante.
Quando seguir
Você apresenta uma data com fuso e explica o que foi guardado. Se ainda precisa de ajuda, repita a experiência pequena antes de avançar.
O arquivo completo
Referência do exemplo 16-datas-horarios, reproduzida aqui para que você possa conferir sem sair da página.
public/index.php
<?php
declare(strict_types=1);
$fuso = new DateTimeZone("America/Recife");
$instante = new DateTimeImmutable("2026-09-14 10:30:00", $fuso);
$registro = $instante->format("c");
$legivel = $instante->format("d/m/Y H:i");
$utc = $instante->setTimezone(new DateTimeZone("UTC"));
?>
<!doctype html>
<html lang="pt-BR">
<head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1">
<title>Livro de visitas de prática</title><link rel="stylesheet" href="estilos.css"></head>
<body><a class="pular" href="#conteudo">Pular para o conteúdo</a>
<header><p>Prática de PHP em pequenos passos</p><h1>Livro de visitas</h1>
<p>Conteúdo fictício. Somente neste computador.</p></header>
<main id="conteudo" tabindex="-1">
<h2>Horário fictício de uma visita</h2><p>Registro: <?= $registro ?></p><p>Em Recife: <?= $legivel ?></p><p>Em UTC: <?= $utc->format("d/m/Y H:i") ?></p>
</main><footer><p>Servidor de estudo em 127.0.0.1. Encerre com Ctrl+C.</p></footer></body></html>
public/estilos.css
* { box-sizing: border-box; }
body { margin: 0; background: #f4f7fb; color: #203246;
font: 1.05rem/1.65 Arial, sans-serif; }
header, main, footer { max-width: 48rem; margin-inline: auto; padding: 1.5rem; }
header { padding-top: 2.5rem; }
h1 { font-size: clamp(1.8rem, 5vw, 2.7rem); line-height: 1.2; }
main { background: #fff; border-radius: .8rem; }
article { border-top: 1px solid #cad4df; padding-block: 1rem; }
a { color: #124e77; text-underline-offset: .2em; }
nav { display: flex; flex-wrap: wrap; gap: 1rem; }
label { display: block; font-weight: bold; }
input:not([type=hidden]), textarea { width: 100%; max-width: 34rem;
border: 2px solid #718095; border-radius: .35rem; padding: .7rem;
font: inherit; color: inherit; background: #fff; }
button { font: inherit; background: #124e77; color: white;
border: 0; border-radius: .35rem; padding: .75rem 1.2rem; cursor: pointer; }
button:hover { background: #103b59; }
.mensagem { white-space: pre-wrap; overflow-wrap: anywhere; }
.erros { color: #8b142c; }
.ok { color: #175c30; font-weight: bold; }
:focus-visible { outline: 3px solid #b04d00; outline-offset: 3px; }
.pular { position: absolute; left: -10000px; }
.pular:focus { position: static; display: block; padding: 1rem; background: white; }
@media (max-width: 35rem) { header,main,footer { padding: 1rem; } }