PHP Datas e Horas
Quase todo sistema lida com datas: a data do pedido, o prazo de entrega, a idade do cliente, quantos dias faltam para o Natal. O PHP tem dois jeitos de trabalhar com elas: as funções clássicas (date, time, strtotime), curtas e diretas, e os objetos DateTime, mais completos para cálculos. E tem uma pegadinha que pega todo brasileiro no primeiro dia: o fuso horário.
- Mostrar a data e a hora com
date(), e as letras de formato (d/m/Y H:i…). - Acertar o fuso:
date_default_timezone_set('America/Sao_Paulo'), e por que a hora sai 3 horas adiantada sem ele. - O que é o timestamp (
time()), e como criar datas commktimeestrtotime('+1 week','next monday'). - Usar
DateTimeeDateTimeImmutable, e por que preferir o segundo. - Ler datas no formato brasileiro (
25/12/2026) sem cair em armadilhas. - Calcular diferenças com
diff(a idade de alguém, dias até uma data). - Escrever os nomes dos meses e dias em português, e validar datas com
checkdate.
A primeira data: date()
date ("data") devolve a data e a hora de agora, formatadas do jeito que você pedir. O formato é um texto em que cada letra vira um pedaço da data:
<?php
echo date('d/m/Y H:i:s'), "\n";
echo date_default_timezone_get(), "\n";
- d
- Dia com dois dígitos (
16,07). - /
- Não é letra de formato: sai como está.
- m
- Mês com dois dígitos (
10). - Y
- Ano com quatro dígitos (
2026). Maiúscula! Oyminúsculo dá só26. - H:i:s
- Hora (0 a 23), minutos e segundos, com dois dígitos. Atenção: minuto é
i, e nãom(que é o mês).
A Ana rodou o programa às 20h56 de uma sexta-feira, em Campinas, e comparou com o relógio do sistema (o comando date do terminal):
$ cd datas $ date sex 16 out 2026 20:56:29 -03 $ php agora.php 16/10/2026 23:56:29 « 3 horas a mais! UTC
O fuso horário
O PHP não sabe onde você está. Se ninguém disser, ele usa o fuso UTC (o "horário universal", de Londres no inverno), que está 3 horas à frente do horário de Brasília. Note que ele não avisa nada: só mostra a hora errada. (Versões muito antigas, até o PHP 5, mostravam um aviso; hoje, silêncio.) Há duas formas de consertar:
- No código, no começo do programa:
<?php date_default_timezone_set('America/Sao_Paulo'); echo date('d/m/Y H:i:s'), "\n"; echo date_default_timezone_get(), "\n";$ php fuso.php 16/10/2026 20:56:29 « agora bate com o relógio America/Sao_Paulo
- No
php.ini(a configuração do PHP, veja Tipos de Erro), valendo para todos os programas:date.timezone = America/Sao_Paulo.
O nome do fuso segue o padrão "Continente/Cidade" (o banco de dados de fusos da IANA). Para o Brasil, os mais usados são America/Sao_Paulo (Brasília, Sul, Sudeste, parte do Nordeste), America/Manaus, America/Cuiaba, America/Rio_Branco, America/Fortaleza, America/Recife, America/Belem e America/Noronha. Escreva exatamente assim, com sublinhado no lugar do espaço. Um nome errado dá aviso e o fuso não muda:
$ php fuso-errado.php « date_default_timezone_set('America/Sao Paulo');
Notice: date_default_timezone_set(): Timezone ID 'America/Sao Paulo' is invalid in /home/ana/datas/fuso-errado.php on line 2
bool(false)
UTC
$ php -d date.timezone=Brasil agora.php « um valor inválido no php.ini
Warning: PHP Startup: Invalid date.timezone value 'Brasil', using 'UTC' instead in Unknown on line 0
16/10/2026 23:56:30
UTC
Experimente: rode e compare as duas linhas com o relógio do seu computador. A primeira usa o fuso padrão do PHP; a segunda, o de Brasília. Troque o fuso por America/Manaus ou Europe/Lisbon e veja a hora mudar.
<?php
echo "Padrão (" . date_default_timezone_get() . "): " . date('d/m/Y H:i') . "\n";
date_default_timezone_set('America/Sao_Paulo');
echo "Brasília: " . date('d/m/Y H:i') . "\n";
As letras de formato
Para a tabela abaixo, a Ana usou sempre a mesma data, sábado, 7 de março de 2026, 14:05:09, passando um segundo argumento ao date (você vai entender esse número na próxima seção). Saídas reais:
| Letra | Significa | Saída |
|---|---|---|
d | Dia, 2 dígitos | 07 |
j | Dia, sem zero | 7 |
D | Dia da semana, abreviado (inglês) | Sat |
l (L minúsculo) | Dia da semana, completo (inglês) | Saturday |
w | Dia da semana, número (0 = domingo … 6 = sábado) | 6 |
N | Dia da semana, ISO (1 = segunda … 7 = domingo) | 6 |
z | Dia do ano (começa em 0) | 65 |
W | Semana do ano (ISO) | 10 |
m | Mês, 2 dígitos | 03 |
n | Mês, sem zero | 3 |
M / F | Mês, abreviado / completo (inglês) | Mar / March |
t | Quantos dias o mês tem | 31 |
L | Ano bissexto? (1 ou 0) | 0 |
Y / y | Ano, 4 / 2 dígitos | 2026 / 26 |
H / G | Hora 00–23 / 0–23 | 14 / 14 |
h / g | Hora 01–12 / 1–12 | 02 / 2 |
a / A | am/pm | pm / PM |
i | Minutos | 05 |
s | Segundos | 09 |
e | Nome do fuso | America/Sao_Paulo |
T / P | Abreviação / diferença para o UTC | -03 / -03:00 |
U | Timestamp | 1772903109 |
c | Data completa ISO 8601 | 2026-03-07T14:05:09-03:00 |
r | Data no formato de e-mail (RFC 2822) | Sat, 07 Mar 2026 14:05:09 -0300 |
Para escrever uma letra sem que ela vire formato, ponha uma barra invertida antes (\h, \d\e):
$ php formatos.php « (final do programa)
…
07/03/2026 às 14h05 « date('d/m/Y \à\s H\hi', $ts)
Saturday, 07 de March de 2026 « date('l, d \d\e F \d\e Y', $ts): nomes em inglês!
Os nomes de dias e meses do date saem sempre em inglês. A solução em português está mais adiante, em Meses e dias em português.
O timestamp: time() e mktime()
Por dentro, o PHP (e quase todo sistema) guarda um momento como um número inteiro: quantos segundos se passaram desde a meia-noite de 1º de janeiro de 1970, no fuso UTC. Esse número se chama timestamp ("carimbo de tempo") ou "tempo Unix". A função time() devolve o timestamp de agora, e date aceita um timestamp como segundo argumento:
<?php
date_default_timezone_set('America/Sao_Paulo');
var_dump(time());
echo date('d/m/Y H:i', 0), "\n";
echo date('d/m/Y H:i', 1000000000), "\n";
$natal = mktime(0, 0, 0, 12, 25, 2026);
echo $natal, "\n";
echo date('d/m/Y', mktime(0, 0, 0, 13, 1, 2026)), "\n";
echo date('d/m/Y', mktime(0, 0, 0, 3, 0, 2026)), "\n";
$ php time.php int(1792194990) « segundos desde 1970 (no momento em que a Ana rodou) 31/12/1969 21:00 « o timestamp 0, no horário de Brasília 08/09/2001 22:46 « o timestamp 1 bilhão 1798167600 « o Natal de 2026, meia-noite 01/01/2027 « "mês 13 de 2026" = janeiro de 2027 28/02/2026 « "dia 0 de março" = último dia de fevereiro
- mktime(hora, minuto, segundo, mês, dia, ano)
- make time, "fabricar o tempo": monta o timestamp de uma data. Cuidado com a ordem estranha: mês antes do dia (herança do formato americano).
- valores "fora do lugar"
- O
mktimenão reclama de mês 13 ou dia 0: ele "transborda" para o mês seguinte ou anterior. Isso é útil (o dia 0 de março dá o último dia de fevereiro) e perigoso (uma data errada vira outra data sem aviso).
Com timestamps, comparar datas e fazer contas é fácil, porque são só números: o maior é o mais recente, e um dia tem 86 400 segundos. Mas contas "na mão" erram em horário de verão e meses de tamanhos diferentes. Para somar dias, semanas e meses, use strtotime ou DateTime.
strtotime: datas escritas em inglês
strtotime ("texto para tempo") lê uma data escrita em texto, inclusive expressões relativas em inglês, e devolve o timestamp (ou false se não entender). O segundo argumento é o "ponto de partida"; sem ele, é agora. A Ana usou como base a sexta-feira 16/10/2026 às 10:00:
<?php
date_default_timezone_set('America/Sao_Paulo');
$base = mktime(10, 0, 0, 10, 16, 2026); // sexta, 16/10/2026 10:00
foreach (['tomorrow', '+1 day', '+1 week', '+2 weeks 3 days', 'next monday', 'last friday', 'first day of next month', 'last day of this month', '2026-12-25', '2026-12-25 18:30', '12/25/2026', '05/12/2026', '25/12/2026', 'amanhã'] as $t) {
$r = strtotime($t, $base);
echo str_pad("'$t'", 28), ' => ', $r === false ? 'false' : date('D d/m/Y H:i', $r), "\n";
}
$ php strtotime.php 'tomorrow' => Sat 17/10/2026 00:00 « amanhã, meia-noite '+1 day' => Sat 17/10/2026 10:00 « 24 horas depois, mesma hora '+1 week' => Fri 23/10/2026 10:00 '+2 weeks 3 days' => Mon 02/11/2026 10:00 'next monday' => Mon 19/10/2026 00:00 « a próxima segunda 'last friday' => Fri 09/10/2026 00:00 « a sexta anterior (não hoje) 'first day of next month' => Sun 01/11/2026 10:00 'last day of this month' => Sat 31/10/2026 10:00 '2026-12-25' => Fri 25/12/2026 00:00 « formato ISO: o mais seguro '2026-12-25 18:30' => Fri 25/12/2026 18:30 '12/25/2026' => Fri 25/12/2026 00:00 « com barras = mês/dia/ano (americano) '05/12/2026' => Tue 12/05/2026 00:00 « PERIGO: virou 12 de MAIO '25/12/2026' => false « não existe mês 25 'amanhã' => false « só entende inglês
strtotime
Com barras, o PHP entende mês/dia/ano. 25/12/2026 falha (ainda bem, você percebe), mas 05/12/2026 vira 12 de maio, sem erro nenhum, e o bolo é entregue sete meses depois. Para ler datas no formato dd/mm/aaaa, use DateTimeImmutable::createFromFormat('d/m/Y', …), que você vai ver daqui a pouco. Para guardar datas (em arquivos e bancos), use o formato ISO 2026-12-25.
Objetos de data: DateTime e DateTimeImmutable
As funções acima trabalham com números soltos. Os objetos DateTime guardam a data e o fuso juntos, e têm métodos para formatar, somar, comparar e calcular diferenças. (Objetos e métodos são assunto do Nível 3; aqui basta a receita: new cria, -> chama um método.)
<?php
date_default_timezone_set('America/Sao_Paulo');
$d = new DateTime('2026-10-16 14:30');
echo $d->format('d/m/Y H:i'), "\n";
$d->modify('+1 day');
echo $d->format('d/m/Y H:i'), "\n";
$e = $d;
$e->modify('+1 month');
echo $d->format('d/m/Y'), " e ", $e->format('d/m/Y'), "\n";
| Trecho | O que faz |
|---|---|
new DateTime('2026-10-16 14:30') | Cria a data. Aceita os mesmos textos do strtotime ('now', 'tomorrow', '+1 week'…). Sem argumento, é agora. |
->format('d/m/Y H:i') | Formata com as mesmas letras do date. |
->modify('+1 day') | Muda a data do próprio objeto. |
$e = $d; | Não copia a data: $e e $d passam a ser o mesmo objeto. |
$ php datetime.php 16/10/2026 14:30 17/10/2026 14:30 17/11/2026 e 17/11/2026 « mexer em $e mudou $d também!
Esse último resultado é a fonte de muitos bugs: você calcula o prazo de entrega a partir da data do pedido e, sem querer, muda a data do pedido. Por isso existe o DateTimeImmutable ("imutável"): os métodos dele nunca mudam o objeto; eles devolvem uma data nova.
<?php
date_default_timezone_set('America/Sao_Paulo');
$pedido = new DateTimeImmutable('2026-10-16');
$entrega = $pedido->modify('+3 days');
echo "Pedido: ", $pedido->format('d/m/Y'), "\n";
echo "Entrega: ", $entrega->format('d/m/Y'), "\n";
$prazo = $pedido->add(new DateInterval('P1M'));
echo "Prazo: ", $prazo->format('d/m/Y'), "\n";
var_dump($entrega > $pedido);
$ php immutable.php Pedido: 16/10/2026 « intacto Entrega: 19/10/2026 Prazo: 16/11/2026 bool(true) « datas se comparam com < > == direto
- $entrega = $pedido->modify('+3 days');
- Com o imutável, guarde o resultado:
$pedido->modify(…)sozinho, sem atribuir, não faz nada. - new DateInterval('P1M')
- Um "intervalo":
P(período) +1M(1 mês). Outros:P3D(3 dias),P1Y2M(1 ano e 2 meses),PT2H(2 horas; oTsepara as horas). - ->add(…) / ->sub(…)
- Somam ou subtraem um intervalo.
Em código novo, prefira DateTimeImmutable. Ele faz tudo o que o DateTime faz, sem o risco de mudar uma data sem querer. Para só mostrar "agora" numa página, date('d/m/Y') continua ótimo.
Missão: o prazo de entrega da lojinha é de 3 dias. O programa abaixo mostra a data do pedido errada (ela mudou junto com a entrega). Troque DateTime por DateTimeImmutable e guarde o resultado do modify em $entrega, para mostrar Pedido: 16/10/2026 e Entrega: 19/10/2026.
<?php
date_default_timezone_set('America/Sao_Paulo');
$pedido = new DateTime('2026-10-16');
$entrega = $pedido;
$entrega->modify('+3 days');
echo "Pedido: " . $pedido->format('d/m/Y') . "\n";
echo "Entrega: " . $entrega->format('d/m/Y') . "\n";
<?php
date_default_timezone_set('America/Sao_Paulo');
$pedido = new DateTimeImmutable('2026-10-16');
$entrega = $pedido->modify('+3 days');
echo "Pedido: " . $pedido->format('d/m/Y') . "\n";
echo "Entrega: " . $entrega->format('d/m/Y') . "\n";
Ler uma data brasileira: createFromFormat
Quando a data vem de um formulário como 25/12/2026, diga ao PHP qual é o formato:
<?php
date_default_timezone_set('America/Sao_Paulo');
$d = DateTimeImmutable::createFromFormat('d/m/Y', '25/12/2026');
echo $d->format('Y-m-d'), "\n";
$x = DateTimeImmutable::createFromFormat('d/m/Y', '31/02/2026');
echo $x->format('d/m/Y'), "\n";
print_r(DateTimeImmutable::getLastErrors());
$y = DateTimeImmutable::createFromFormat('d/m/Y', 'ontem');
var_dump($y);
$ php fromformat.php
2026-12-25 « entendeu dia/mês/ano
03/03/2026 « 31 de fevereiro "transbordou" para 3 de março!
Array
(
[warning_count] => 1
[warnings] => Array
(
[10] => The parsed date was invalid « mas ficou um aviso guardado
)
[error_count] => 0
[errors] => Array
(
)
)
bool(false) « texto que não segue o formato: false
Os dois pontos de atenção: createFromFormat devolve false quando o texto não tem o formato pedido, e aceita datas impossíveis como 31/02, "transbordando" para março. Para recusar datas impossíveis, confira com checkdate (no fim da aula) ou com getLastErrors(). E o :: em DateTimeImmutable::createFromFormat chama um método da classe, sem objeto (um método estático).
Já o new DateTime('25/12/2026') não tenta adivinhar: lança uma exceção:
$ php malformed.php « $d = new DateTime('25/12/2026');
Fatal error: Uncaught DateMalformedStringException: Failed to parse time string (25/12/2026) at position 0 (2): Unexpected character in /home/ana/datas/malformed.php:2
Stack trace:
#0 /home/ana/datas/malformed.php(2): DateTime->__construct('25/12/2026')
#1 {main}
thrown in /home/ana/datas/malformed.php on line 2
"Falha ao interpretar o texto de data". A exceção DateMalformedStringException existe desde o PHP 8.3+ (antes era uma Exception comum, com a mesma mensagem).
Diferença entre datas: diff (e a idade)
$a->diff($b) calcula o intervalo entre duas datas, em anos, meses e dias de calendário (levando em conta meses de 28, 30 ou 31 dias e anos bissextos). É o jeito certo de calcular uma idade:
<?php
date_default_timezone_set('America/Sao_Paulo');
$nascimento = new DateTimeImmutable('1997-03-15');
$hoje = new DateTimeImmutable('2026-10-16');
$diff = $nascimento->diff($hoje);
echo "Idade: {$diff->y} anos\n";
echo $diff->format('%y anos, %m meses e %d dias'), "\n";
echo "Dias vividos: {$diff->days}\n";
echo $diff->format('%a dias'), "\n";
$natal = new DateTimeImmutable('2026-12-25');
echo "Faltam ", $hoje->diff($natal)->days, " dias para o Natal\n";
var_dump($natal->diff($hoje)->invert);
$ php idade.php Idade: 29 anos 29 anos, 7 meses e 1 dias « o format não sabe fazer plural: "1 dias" Dias vividos: 10807 10807 dias Faltam 70 dias para o Natal int(1) « 1 = o intervalo é "para trás" (a 2ª data é anterior)
| No intervalo | O que é | No format |
|---|---|---|
->y, ->m, ->d | Anos, meses e dias "de calendário" | %y, %m, %d |
->h, ->i, ->s | Horas, minutos, segundos | %h, %i, %s |
->days | Total de dias entre as datas | %a |
->invert | 1 se a segunda data é anterior à primeira | %R mostra + ou - |
Num programa de verdade, $hoje seria new DateTimeImmutable('today'). Aqui a Ana fixou a data para o resultado não mudar a cada dia.
Meses e dias em português
O date e o format só escrevem em inglês. O jeito mais simples (e que funciona em qualquer PHP) é ter os nomes num array e usar os números que o format dá: n (mês de 1 a 12) e w (dia da semana de 0 a 6, começando no domingo).
<?php
date_default_timezone_set('America/Sao_Paulo');
$meses = [1 => 'janeiro', 'fevereiro', 'março', 'abril', 'maio', 'junho',
'julho', 'agosto', 'setembro', 'outubro', 'novembro', 'dezembro'];
$dias = ['domingo', 'segunda-feira', 'terça-feira', 'quarta-feira',
'quinta-feira', 'sexta-feira', 'sábado'];
$d = new DateTimeImmutable('2026-10-16');
echo $dias[$d->format('w')] . ', ' . $d->format('j') . ' de '
. $meses[$d->format('n')] . ' de ' . $d->format('Y') . "\n";
$ php meses.php sexta-feira, 16 de outubro de 2026
- [1 => 'janeiro', 'fevereiro', …]
- O
1 =>faz o array começar na chave 1; os próximos ganham 2, 3… Assim$meses[10]é'outubro', sem precisar subtrair 1. - $dias
- Começa em 0 (domingo), igual ao
w.
O PHP tem uma extensão de internacionalização, a intl, com a classe IntlDateFormatter, que escreve datas em qualquer idioma. Ela não vem em toda instalação: no Ubuntu/Debian é o pacote php-intl. O php que a Ana usa no dia a dia (e o do editor do guia) não tem:
$ php intl.php « var_dump(extension_loaded('intl')); new IntlDateFormatter(…);
bool(false)
Fatal error: Uncaught Error: Class "IntlDateFormatter" not found in /home/ana/datas/intl.php:3
Stack trace:
#0 {main}
thrown in /home/ana/datas/intl.php on line 3
A Ana tem, na mesma máquina, uma segunda instalação do PHP com mais extensões, que ela chama pelo comando php-completo. Nela, a intl existe:
<?php
var_dump(extension_loaded('intl'));
$data = new DateTimeImmutable('2026-10-16', new DateTimeZone('America/Sao_Paulo'));
$fmt = new IntlDateFormatter('pt_BR', IntlDateFormatter::FULL, IntlDateFormatter::NONE, 'America/Sao_Paulo');
echo $fmt->format($data), "\n";
$fmt = new IntlDateFormatter('pt_BR', IntlDateFormatter::LONG, IntlDateFormatter::SHORT, 'America/Sao_Paulo');
echo $fmt->format($data), "\n";
$fmt = new IntlDateFormatter('pt_BR', IntlDateFormatter::NONE, IntlDateFormatter::NONE, 'America/Sao_Paulo', null, "EEEE, d 'de' MMMM");
echo $fmt->format($data), "\n";
$fmt = new IntlDateFormatter('pt_BR', IntlDateFormatter::NONE, IntlDateFormatter::NONE, 'America/Sao_Paulo', null, 'MMM/yy');
echo $fmt->format($data), "\n";
$ php-completo intl2.php bool(true) sexta-feira, 16 de outubro de 2026 « FULL: data completa, sem hora (NONE) 16 de outubro de 2026 às 00:00 « LONG para a data, SHORT para a hora sexta-feira, 16 de outubro « um modelo próprio (letras do padrão ICU, diferentes das do date!) out./26
Os argumentos são: o idioma ('pt_BR'), o estilo da data, o estilo da hora (FULL, LONG, MEDIUM, SHORT ou NONE), o fuso e, opcionalmente, o calendário e um modelo. Cuidado: os modelos da intl usam outras letras (EEEE = dia da semana, MMMM = mês por extenso, yy = ano com 2 dígitos).
Confira sempre com extension_loaded('intl') antes, ou fique com o array, que funciona em qualquer lugar.
Validar: checkdate e conversão de fusos
checkdate(mês, dia, ano) responde se a data existe de verdade (de novo, mês antes do dia):
<?php var_dump(checkdate(2, 29, 2026)); var_dump(checkdate(2, 29, 2028)); var_dump(checkdate(4, 31, 2026)); var_dump(checkdate(12, 25, 2026));
$ php checkdate.php bool(false) « 2026 não é bissexto bool(true) « 2028 é bool(false) « abril tem 30 dias bool(true)
E para mostrar o mesmo momento em outro fuso (o cliente de Manaus, a fornecedora em Lisboa), use setTimezone:
<?php
$sp = new DateTimeImmutable('2026-10-16 14:30', new DateTimeZone('America/Sao_Paulo'));
echo $sp->format('d/m/Y H:i T P'), "\n";
echo $sp->setTimezone(new DateTimeZone('Europe/Lisbon'))->format('d/m/Y H:i T P'), "\n";
echo $sp->setTimezone(new DateTimeZone('America/Manaus'))->format('d/m/Y H:i T P'), "\n";
echo $sp->setTimezone(new DateTimeZone('UTC'))->format('d/m/Y H:i T P'), "\n";
$ php zonas.php 16/10/2026 14:30 -03 -03:00 16/10/2026 18:30 WEST +01:00 « horário de verão de Portugal (outubro) 16/10/2026 13:30 -04 -04:00 16/10/2026 17:30 UTC +00:00
Quando dá errado
O que significa: o PHP está usando o fuso UTC (o padrão, sem aviso).
Como consertar: date_default_timezone_set('America/Sao_Paulo'); no começo do programa (ou num arquivo de configuração incluído por todas as páginas), ou date.timezone = America/Sao_Paulo no php.ini.
Notice: date_default_timezone_set(): Timezone ID 'America/Sao Paulo' is invalid in /home/ana/datas/fuso-errado.php on line 2
Como consertar: o nome tem sublinhado: America/Sao_Paulo. Com new DateTimeZone('Brasil/Campinas') o erro é uma exceção: Fatal error: Uncaught DateInvalidTimeZoneException: DateTimeZone::__construct(): Unknown or bad timezone (Brasil/Campinas). A lista completa sai de DateTimeZone::listIdentifiers().
O que significa: strtotime ou new DateTime receberam uma data com barras, que eles leem como mês/dia/ano.
Como consertar: DateTimeImmutable::createFromFormat('d/m/Y', $texto), conferindo se o resultado não é false.
Fatal error: Uncaught DateMalformedStringException: Failed to parse time string (25/12/2026) at position 0 (2): Unexpected character in /home/ana/datas/malformed.php:2
O que significa: o texto passado a new DateTime(…) não é uma data que o PHP entenda ("posição 0, caractere 2: inesperado").
Como consertar: use o formato ISO (2026-12-25) ou createFromFormat; se o texto vem do usuário, trate a exceção com try/catch (veja Exceções).
Referência
| Item | O que faz |
|---|---|
date($formato, $ts) | Formata o timestamp (padrão: agora). |
time() | Timestamp de agora (segundos desde 1970). |
mktime(h, i, s, mês, dia, ano) | Monta um timestamp. |
strtotime($texto, $base) | Texto (em inglês) → timestamp, ou false. |
checkdate(mês, dia, ano) | A data existe? |
date_default_timezone_set($fuso) / _get() | Define / mostra o fuso padrão. |
new DateTimeImmutable($texto, $fuso) | Cria uma data imutável. |
DateTimeImmutable::createFromFormat('d/m/Y', $t) | Lê uma data num formato conhecido. |
->format($f) | Formata (mesmas letras do date). |
->modify('+1 week'), ->add(new DateInterval('P3D')), ->sub(…) | Somam/subtraem (no imutável, devolvem uma data nova). |
$a->diff($b) | Intervalo: ->y, ->m, ->d, ->days, ->invert. |
->setTimezone(new DateTimeZone('…')) | O mesmo momento em outro fuso. |
->getTimestamp() | O timestamp do objeto. |
Exercícios
1. Formato brasileiro
Complete para mostrar algo como 16/10/2026:
2. O fuso de Brasília
Complete:
3. Uma semana depois
Complete para calcular a data uma semana depois de $pedido (um DateTimeImmutable):
4. No date, qual letra mostra os minutos?
5. O que strtotime('05/12/2026') devolve?
6. Com $a = new DateTimeImmutable('2026-10-16'); $a->modify('+1 day'); echo $a->format('d');, o que aparece?
Missão final: complete a função ficha. Ela recebe o nome e a data de nascimento no formato brasileiro e, considerando que hoje é 16/10/2026: (1) se a data não existir, mostra Data inválida: 31/02/2026; (2) senão, mostra a idade (Bia tem 29 anos), o próximo aniversário por extenso em português (Aniversário: segunda-feira, 15 de março de 2027) e quantos dias faltam (Faltam 150 dias). Dica: explode('/', $texto) separa dia, mês e ano para o checkdate; o próximo aniversário é a data de nascimento com o ano de hoje, ou do ano seguinte se já passou.
<?php
date_default_timezone_set('America/Sao_Paulo');
$meses = [1 => 'janeiro', 'fevereiro', 'março', 'abril', 'maio', 'junho',
'julho', 'agosto', 'setembro', 'outubro', 'novembro', 'dezembro'];
$dias = ['domingo', 'segunda-feira', 'terça-feira', 'quarta-feira',
'quinta-feira', 'sexta-feira', 'sábado'];
$hoje = new DateTimeImmutable('2026-10-16');
function ficha(string $nome, string $nascimento): void
{
global $meses, $dias, $hoje;
// seu código aqui
}
ficha('Bia', '15/03/1997');
ficha('Caio', '31/02/2026');
<?php
date_default_timezone_set('America/Sao_Paulo');
$meses = [1 => 'janeiro', 'fevereiro', 'março', 'abril', 'maio', 'junho',
'julho', 'agosto', 'setembro', 'outubro', 'novembro', 'dezembro'];
$dias = ['domingo', 'segunda-feira', 'terça-feira', 'quarta-feira',
'quinta-feira', 'sexta-feira', 'sábado'];
$hoje = new DateTimeImmutable('2026-10-16');
function ficha(string $nome, string $nascimento): void
{
global $meses, $dias, $hoje;
[$d, $m, $a] = array_map('intval', explode('/', $nascimento));
if (!checkdate($m, $d, $a)) {
echo "Data inválida: $nascimento\n";
return;
}
$nasc = DateTimeImmutable::createFromFormat('!d/m/Y', $nascimento);
echo "$nome tem {$nasc->diff($hoje)->y} anos\n";
$aniv = $nasc->setDate((int) $hoje->format('Y'), $m, $d);
if ($aniv < $hoje) {
$aniv = $aniv->modify('+1 year');
}
echo "Aniversário: " . $dias[$aniv->format('w')] . ', ' . $aniv->format('j')
. ' de ' . $meses[$aniv->format('n')] . ' de ' . $aniv->format('Y') . "\n";
echo "Faltam {$hoje->diff($aniv)->days} dias\n";
}
ficha('Bia', '15/03/1997');
ficha('Caio', '31/02/2026');
Na solução aparecem dois detalhes novos: o ! no começo do formato ('!d/m/Y') zera a hora: sem ele, a data recebe a hora do momento em que o programa roda (quando a Ana testou, createFromFormat('d/m/Y', '15/03/2027') deu 15/03/2027 20:59:04); misturar datas com e sem hora deixa comparações como $aniv < $hoje difíceis de prever, e setDate(ano, mês, dia) troca a data mantendo o resto. O global deixa a função usar as variáveis de fora (veja Escopo); num programa maior, você passaria esses valores como parâmetros.
Resumo
date('d/m/Y H:i')mostra data e hora; cada letra é um pedaço (minuto éi; ano com 4 dígitos éY).- Sem fuso definido, o PHP usa UTC (3 horas à frente de Brasília) e não avisa: use
date_default_timezone_set('America/Sao_Paulo')ou ophp.ini. - Timestamp = segundos desde 1970:
time(),mktime()(mês antes do dia!). strtotimeentende inglês ('+1 week','next monday'), mas lê05/12/2026como 12 de maio.- Prefira
DateTimeImmutable:format,modify,add,diff, e guarde sempre o resultado. - Datas brasileiras:
createFromFormat('d/m/Y', …)+checkdate. - Nomes em português: um array de meses e dias (ou
IntlDateFormatter, se a extensãointlexistir).
Próxima aula: Tipos de Erro, para entender os Warning, Notice e Fatal error que apareceram até aqui.