--- name: PHP do servidor está em UTC — usar helpers timestampBrasilia/formatarBrasilia description: PHP de produção tem date.timezone=UTC. Datas no banco estão em horário Brasília. strtotime/date direto causa offset de 3h. type: feedback originSessionId: 86576285-fa7a-44f0-8ed3-9a88bcd27a8e --- ## Bug recorrente: PHP servidor em UTC + datas no banco em BR ### Diagnóstico - `php -r 'echo date_default_timezone_get();'` → **UTC** - Datas no banco são salvas pelo `agoraBrasilia()` (string Y-m-d H:i:s sem timezone) → estão em horário Brasília - `strtotime("2026-05-05 11:11:55")` interpreta como **UTC** → timestamp UTC 11:11:55 (= 14:11:55 BR) - `date('H:i:s', $ts)` em PHP UTC → mostra horário UTC - **Resultado**: cálculos de tempo decorrido erram em **3h**, formatações exibem +3h ### Sintoma observado - Cronômetro do app professor mostrava `03:40:52` em vez de `00:40:52` (40min) - Histórico de aulas concluídas no banco com horários +3h ("Início real: 14:11:55" quando real era 11:11:55) - API `/aulas/hoje` mostrava aulas do dia errado entre 21h-00h BR (date('Y-m-d') em UTC) ### Solução padrão — helpers em ApiProfessorController ```php private function timestampBrasilia(?string $datetime): int { if (empty($datetime)) return 0; return (new \DateTime($datetime, new \DateTimeZone('America/Sao_Paulo')))->getTimestamp(); } private function formatarBrasilia(int $timestamp, string $formato = 'H:i:s'): string { if ($timestamp <= 0) return ''; return (new \DateTime('@' . $timestamp)) ->setTimezone(new \DateTimeZone('America/Sao_Paulo')) ->format($formato); } private function dataBrasilia(string $formato = 'Y-m-d'): string { return (new \DateTime('now', new \DateTimeZone('America/Sao_Paulo')))->format($formato); } ``` ### Onde aplicar - **Toda chamada `strtotime($coluna_datetime_do_banco)`** → trocar por `$this->timestampBrasilia($coluna)` - **Toda chamada `date('H:i:s', $ts)`** onde $ts veio de timestampBrasilia → trocar por `formatarBrasilia($ts)` - **Toda chamada `date('Y-m-d')`** que precisa do "hoje" do usuário → trocar por `dataBrasilia()` ### Frontend (JS) — calibração de relógio Se o backend retorna `server_time` em horário Brasília (sem `Z`), no JS: ```js // ❌ ERRADO (trata como UTC): new Date(serverTimeStr.replace(' ', 'T') + 'Z') // ✅ CERTO (trata como Brasília): new Date(serverTimeStr.replace(' ', 'T') + '-03:00') ``` **Importante**: ambos `calibrarRelogio` e `calcularTempoEfetivo` precisam usar o MESMO offset, caso contrário a diferença fica negativa e o timer mostra `00:00`. **Why**: shared hosting frequentemente está em UTC. Não dá pra alterar `date.timezone` global. Solução é blindar todos pontos de conversão. **How to apply**: ao adicionar nova rota que faça aritmética de tempo com colunas de data do banco, SEMPRE usar os helpers acima. `time()` puro continua OK (já é UTC). ### Aulas históricas com horário errado Houve um período (manhã 2026-05-05) em que dois bugs se cancelavam (strtotime UTC + date UTC = horário literal certo). Após primeira correção, ficaram +3h. Script `php` único em `/tmp/fix_obs.php` corrigiu observações via regex (somar/subtrair 3h baseado em comparação com horario_inicio do banco).