
Trocou DateTime por DateTimeImmutable e o ->modify('+1 day') parou de fazer efeito. Não parou: ele nunca alterou o objeto. Todo método de mudança da classe imutável devolve uma instância nova e deixa a original intacta. Se você não guardar o retorno, jogou fora o resultado.
<?php
$d = new DateTimeImmutable('2026-08-31 10:00', new DateTimeZone('America/Sao_Paulo'));
$d->modify('+1 day');
echo $d->format('Y-m-d'), PHP_EOL; // 2026-08-31 — retorno descartado
$d = $d->modify('+1 day');
echo $d->format('Y-m-d'), PHP_EOL; // 2026-09-01 Vale o mesmo para add, sub, setTime, setDate e setTimezone. A regra prática: nessa classe, o retorno é o único lugar onde a mudança existe.
<?php
$inicio = new DateTimeImmutable('2026-09-01');
$dias = [];
for ($i = 0; $i < 5; $i++) {
$dias[] = $inicio->add(new DateInterval('P' . $i . 'D'));
}
foreach ($dias as $dia) {
echo $dia->format('d/m'), PHP_EOL; // 01/09 02/09 03/09 04/09 05/09
} Troque a primeira linha por DateTime e o mesmo laço imprime 11/09 cinco vezes. O array guarda cinco referências ao único objeto que existe, e cada add empurra ele mais pra frente até somar os dez dias do acumulado. É o clássico do relatório que sai com todas as linhas na mesma data, e o motivo de eu usar a versão imutável como padrão em cálculo de prazo.
Até o PHP 8.2, string de data inválida em modify() soltava um Warning e devolvia false — com display_errors desligado, o erro só aparecia lá na frente, na forma de uma data errada. No 8.3 ela lança DateMalformedStringException. Se o texto vem do usuário ou de planilha importada, embrulhe a chamada.
try {
$ate = $inicio->modify($_POST['ate'] ?? '');
} catch (DateMalformedStringException $e) { // PHP 8.3+
$ate = $inicio->modify('+30 days');
} Se o projeto ainda roda 8.2, o teste é contra false antes de usar o valor. Migrar pro 8.3 só troca onde o erro aparece: agora ele derruba a requisição em vez de contaminar o cálculo silenciosamente.
strtotime com data brasileira devolve false e o INSERT quebra no MySQL 8. Use createFromFormat com getLastErrors antes de mandar…
O hash que o Magento mostra junto do erro é o nome de um arquivo em var/report. Veja como abrir,…
Seu snippet com woocommerce_checkout_fields parou de aparecer no checkout em blocos. Registre o campo pela API nova e leia o…
O pedido entrou às 21h e o relatório mostra 00h do dia seguinte. Onde setar date.timezone no PHP 8.3 e…
O pedido entra na loja e o e-mail nunca sai: antes de culpar o SMTP, veja o envio assíncrono, a…
O WordPress só oferece hourly, twicedaily, daily e weekly. Use o filtro cron_schedules para criar um intervalo de 5 minutos…