Se você já publicou um post apenas para vê-lo rotulado como “57 anos atrás” no site público, enquanto seu painel insiste calmamente que ele foi postado há dez minutos após a hora, você conhece a dor particular deste bug. Ele não quebra o layout. Não gera um erro fatal. Ele simplesmente envelhece seu conteúdo em meio século, e ficar encarando os arquivos do seu tema não fará o número mudar.

Este problema tende a sobreviver às verificações habituais. Você faz um grep em single.php, archive.php e functions.php procurando por uma chamada get_the_date() corrompida. Tudo parece padrão. Você recarrega a página ao vivo. O fantasma de 1968 ainda assombra sua linha de autoria. Nesse ponto, o problema quase não tem nada a ver com seus templates e tudo a ver com a forma como o tempo passa pela stack do WordPress.

Por que esse número específico continua aparecendo

O número “57 anos atrás” não é aleatório. Os temas do WordPress frequentemente exibem o tempo relativo por meio da função human_time_diff(), que compara o timestamp de um post com o momento atual e imprime uma frase amigável como “2 horas atrás”. Para que esse cálculo funcione, o PHP precisa de um Unix timestamp válido — uma contagem de segundos desde 1º de janeiro de 1970, a era Unix (Unix epoch).

Quando algo remove ou corrompe o timestamp antes que ele chegue a esse cálculo, a função frequentemente acaba comparando o zero (ou um ponto de partida invalidamente semelhante) com o agora. O resultado é um intervalo que retrocede aproximadamente cinco décadas e meia, avançando um ano de cada vez. É um sintoma de um valor de tempo ausente ou lido incorretamente, não de um banco de dados cheio de posts de blogs retrô.

O Engano do Painel de Controle

Um dos aspectos mais frustrantes deste bug é a personalidade dividida do seu painel administrativo. Dentro do wp-admin, a lista de Posts mostra a data de publicação correta porque o WordPress geralmente a extrai diretamente da tabela MySQL wp_posts e a formata no lado do servidor, sem passar pelo filtro de tempo relativo. O frontend, no entanto, pode depender de um tema ou plugin que chama human_time_diff(), ou pode passar o valor bruto do banco de dados por uma cadeia de conversões de fuso horário do PHP que o backend ignora completamente.

Portanto, os dados geralmente ainda estão intactos. É o pipeline entre o banco de dados e o HTML renderizado que apresenta um problema.

Versão do PHP e Configurações de Fuso Horário

Comece pelo PHP. Painéis de hospedagem fazem as trocas de versão parecerem inofensivas, mas o PHP lida com objetos de tempo de forma diferente entre as principais versões. Um site executando código legado de PHP 7.4 em um ambiente repentino de PHP 8.1 pode encontrar mudanças sutis na forma como os objetos DateTime inicializam strings vazias ou malformadas. Se o seu arquivo php.ini deixar o date.timezone indefinido, o PHP assume o UTC por padrão e pressupõe que o servidor sabe o que é melhor. O WordPress pode discordar.

Verifique se alguém inseriu manualmente uma declaração de fuso horário dentro do wp-config.php. Uma linha como date_default_timezone_set( 'Asia/Kolkata' ); parece útil, mas o WordPress espera gerenciar seu próprio relógio por meio do valor definido em Configurações > Geral. Forçar um deslocamento (offset) no nível do PHP pode criar uma condição de corrida (race condition) onde o núcleo (core) acredita que o horário é local e o PHP acredita que é universal. Quando esses deslocamentos colidem durante uma conversão de timestamp, o resultado retornado ao seu template pode colapsar para zero.

Configurações de Fuso Horário do Servidor

Seu servidor MySQL tem sua própria ideia de horário local. O WordPress escreve duas datas para cada post: post_date no horário local do site e post_date_gmt no Horário Universal (UTC). Se o time_zone global do banco de dados mudar — por exemplo, de SYSTEM para +00:00 após uma migração — o strtotime() do PHP pode falhar ao reconciliar a string armazenada com o que ele espera. O banco de dados ainda armazena 2024-03-15 14:30:00, mas o contexto ao redor muda, e a saída analisada torna-se false ou null no PHP.

Exemplo do mundo real: uma hospedagem gerenciada move seu banco de dados de um nó executando MySQL 5.7 com o horário SYSTEM para um cluster executando MariaDB 10.11 configurado para UTC estrito. Seu tema nunca muda. Suas configurações do WordPress nunca mudam. No entanto, get_the_time( 'U' ) — o formato Unix timestamp — de repente retorna um valor vazio para alguns posts, e a função de tempo relativo recorre àquele cálculo de época zero. A solução é alinhar o fuso horário da aplicação, o fuso horário do banco de dados e o relógio do sistema operacional para que o WordPress não precise adivinhar qual referencial usar.

Formatos de Timestamp do Banco de Dados

O núcleo do WordPress armazena as datas dos posts em colunas DATETIME do MySQL, não em campos TIMESTAMP. Essa distinção é importante porque o DATETIME mantém um valor de calendário sem consciência de fuso horário em versões mais antigas do MySQL, enquanto o TIMESTAMP converte tudo para UTC nos bastidores. Se um plugin ou ferramenta de migração alterou o esquema da sua wp_posts, ou se um backup antigo restaurou datas zero inválidas na tabela, o WordPress pode ler um valor como 0000-00-00 00:00:00 e passá-lo silenciosamente para o seu tema.

Os modos modernos do MySQL, particularmente NO_ZERO_DATE e STRICT_TRANS_TABLES, rejeitam esses marcadores de posição zero. Se um script de backup os inseriu durante uma migração, o banco de dados pode tê-los truncado ou transformado em nulo durante a importação. Você pode verificar isso rapidamente com uma consulta SQL direta:

SELECT ID, post_title, post_date, post_date_gmt 
FROM wp_posts 
WHERE post_status = 'publish' 
ORDER BY post_date DESC 
LIMIT 10;

Se as colunas brutas parecerem corretas, mas o site ainda exibir um histórico antigo, a corrupção está ocorrendo após a consulta. Se as próprias colunas contiverem zeros, você encontrou o vazamento no encanamento.

Conflitos de Plugins com Funções de Data

Plugins que filtram a saída de datas são culpados comuns. Ferramentas multilíngues como WPML ou Polylang utilizam hooks no get_the_date para traduzir nomes de meses. Plugins de cache interceptam o HTML final. Qualquer uma dessas camadas pode acidentalmente passar uma string não formatada para uma função que espera um inteiro Unix.

Um plugin de tradução pode substituir “March 15, 2024” por seu equivalente localizado, mas se um tema então passar essa string localizada para o strtotime() dentro de uma função personalizada, o parser falhará em caracteres que não sejam em inglês e retornará false. Esse valor falso chega ao human_time_diff(), que compara zero com o momento atual, produzindo o infame intervalo de meio século.

Camadas de cache de objetos complicam ainda mais isso. Redis ou Memcached podem armazenar um objeto WP_Post serializado de uma requisição que falhou brevemente ao analisar a data. Cada visitante subsequente recebe esse objeto corrompido diretamente da RAM, ignorando completamente o banco de dados. O problema persiste no site ao vivo porque sua stack de produção possui uma infraestrutura de cache que sua instalação local não possui.

Um Checklist Prático de Depuração

Como o sintoma se esconde profundamente na stack, você precisa remover as camadas sistematicamente até que as datas voltem ao normal.

  1. Consulte o banco de dados diretamente. Abra o phpMyAdmin ou execute o WP-CLI e inspecione os valores brutos de post_date. Se estiverem corretos, o banco de dados não é o problema.
  2. Mude para um tema padrão. Ative o Twenty Twenty-Four ou Twenty Twenty-Three. Se o erro desaparecer, audite seu tema ativo e tema filho em busca de funções personalizadas que envolvam a saída de tempo.
  3. Silencie os plugins. Renomeie a pasta /wp-content/plugins temporariamente ou desative todos os plugins pelo painel. Reative-os um por um, verificando o frontend após cada ativação.
  4. Leia o log de erros. Procure por avisos de fuso horário, erros de DateTime ou reclamações de strtotime(). Eles geralmente apontam para o exato