1927: O momento em que o tempo andou para trás
\n\nImagine: você está escrevendo um script simples em Java para calcular a diferença entre duas datas em milissegundos. Você pega o ano de 1927, subtrai um valor do outro — e obtém não 3600 segundos (uma hora), mas um número estranho. Você verifica o código novamente, pesquisa no Google, encontra a lendária pergunta no StackOverflow com milhares de visualizações. E percebe: você não está sozinho.
\n\nEsse bug é um verdadeiro artefato histórico que ainda assusta iniciantes. Neste artigo, vamos analisar por que subtrair epoch-milli times em 1927 dá um resultado estranho, mostrar exemplos reais de código Java e, principalmente, dar maneiras práticas de evitar essa armadilha. Se você trabalha com dados históricos ou apenas quer escrever código confiável — esta informação é para você.
\n\nEssência do problema: A magia de 31 de dezembro de 1927
\n\nVamos direto ao código. Aqui está um exemplo clássico que confunde a mente:
\n\nimport java.util.TimeZone;\nimport java.text.SimpleDateFormat;\nimport java.util.Date;\n\npublic class StrangeDateDifference {\n public static void main(String[] args) throws Exception {\n TimeZone tz = TimeZone.getTimeZone("Asia/Shanghai");\n SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");\n sdf.setTimeZone(tz);\n\n Date date1 = sdf.parse("1927-12-31 23:54:07");\n Date date2 = sdf.parse("1927-12-31 23:54:08");\n\n long diff = date2.getTime() - date1.getTime();\n System.out.println("Diferença em milissegundos: " + diff);\n // Esperamos 1000, mas obtemos...\n }\n}\n\nVocê executa — e em vez de 1000 milissegundos (1 segundo), vê 353? Ou até um número negativo? Parabéns, você encontrou o erro de subtração de datas de 1927.
\n\nA causa não é um bug do Java (embora também haja um, mas falaremos disso depois). A causa é uma mudança histórica no fuso horário. Em 31 de dezembro de 1927, em Xangai (Asia/Shanghai), aconteceu algo estranho: às 23:54:08, o horário local foi atrasado em 5 minutos e 52 segundos. Na prática, o segundo durou não 1000 ms, mas apenas 353 ms. O Java processa honestamente esse fato histórico, mas para o desenvolvedor, isso parece mágica.
\n\nTop erros que os desenvolvedores cometem
\n\n1. Confiança cega em APIs antigas (java.util.Date e SimpleDateFormat)
\n\nO primeiro e mais popular erro é usar as classes obsoletas java.util.Date e SimpleDateFormat. Elas não são apenas inconvenientes, mas também contêm surpresas ocultas, especialmente ao trabalhar com datas históricas.
Como evitar: Use java.time (Java 8+). Por exemplo:
import java.time.LocalDateTime;\nimport java.time.ZoneId;\nimport java.time.ZonedDateTime;\nimport java.time.format.DateTimeFormatter;\n\npublic class SafeDateDifference {\n public static void main(String[] args) {\n DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");\n ZoneId zone = ZoneId.of("Asia/Shanghai");\n\n LocalDateTime ldt1 = LocalDateTime.parse("1927-12-31 23:54:07", formatter);\n LocalDateTime ldt2 = LocalDateTime.parse("1927-12-31 23:54:08", formatter);\n\n ZonedDateTime zdt1 = ldt1.atZone(zone);\n ZonedDateTime zdt2 = ldt2.atZone(zone);\n\n long diff = zdt2.toInstant().toEpochMilli() - zdt1.toInstant().toEpochMilli();\n System.out.println("Diferença em milissegundos: " + diff);\n // Ainda assim obterá um número estranho, mas pelo menos saberá o porquê!\n }\n}\n\n2. Ignorar mudanças históricas nos fusos horários
\n\nMuitos pensam que os fusos horários são apenas um deslocamento fixo em relação ao UTC. Mas, na verdade, eles mudaram dezenas de vezes nos últimos 100 anos.