O pedido entrou às 21h de ontem e o relatório mostra 00h de hoje. Não é bug do relatório: o PHP 8.3 está rodando em UTC porque ninguém preencheu date.timezone, e três horas entram ou somem em todo date() do projeto.
Onde setar de verdade
FPM e CLI leem arquivos ini diferentes, e o php -i do terminal só mostra o do CLI. Ajustar um e esquecer o outro deixa o painel certo e o cron errado. O .bak do sed é o seu plano B se o serviço não subir:
php -i | grep '^date.timezone'
sudo sed -i.bak 's|^;?date.timezone =.*|date.timezone = America/Sao_Paulo|'
/etc/php/8.3/fpm/php.ini /etc/php/8.3/cli/php.ini
sudo systemctl reload php8.3-fpmO php.ini da distro entrega a linha comentada, do jeito ;date.timezone =. Sem valor o PHP assume UTC calado: o aviso de fuso indefinido saiu no PHP 7.0. Se a hospedagem não te dá o ini, chame date_default_timezone_set('America/Sao_Paulo') na primeira linha do bootstrap, antes de qualquer formatação de data.
O banco continua em UTC
Resista à vontade de gravar horário de Brasília na coluna. Guarde UTC e converta só na exibição, senão no dia em que o horário de verão voltar você fica com duas horas iguais na mesma tabela. O offset numérico ainda dispensa carregar as tabelas de fuso do MySQL 8:
SELECT id, CONVERT_TZ(date_created_gmt, '+00:00', '-03:00') AS criado_br
FROM wp_wc_orders ORDER BY id DESC LIMIT 5;Na aplicação vale o mesmo raciocínio: leia como UTC, mostre no fuso de quem está olhando.
$d = new DateTimeImmutable($linha['date_created_gmt'], new DateTimeZone('UTC'));
echo $d->setTimezone(new DateTimeZone('America/Sao_Paulo'))->format('d/m/Y H:i');Depois do reload, rode php -r 'echo date_default_timezone_get();' no CLI e abra um phpinfo() pelo navegador. Se os dois não devolverem America/Sao_Paulo, o painel bate e o cron da meia-noite não.