Calcular idade manualmente versus em código
Muita gente acha que subtrair o ano de nascimento do ano atual resolve. Não resolve. Se você nasceu em dezembro de 2000 e a data de hoje é março de 2024, a conta simples daria 24 anos, mas a pessoa ainda não fez aniversário nesse ano, então a idade correta é 23. O erro mais comum que eu já vi em sistemas legítimos é exatamente esse: comparar só os anos e ignorar mês e dia. Na prática, o algoritmo certo funciona assim. Você pega a data atual, a data de nascimento, e verifica se o mês e dia de aniversário já passaram neste ano. Se sim, a idade é ano_atual menos ano_nascimento. Se não, subtrai mais um. Parece óbvio quando você vê escrito, mas implementações apressadas frequentemente pulam essa verificação e retornam uma idade errada em cerca de 30% dos casos, dependendo de quando o sistema foi rodado durante o ano.
Quantos anos tem uma pessoa: o problema prático
Eu já passei por isso numa rotina de validação de documentos. O sistema precisava verificar se o usuário tinha pelo menos 18 anos para acessar certas funcionalidades. A primeira versão do código usava uma biblioteca de datas que calculava a diferença em dias e dividia por 365. Funcionou bem até o dia em que testamos com alguém nascido em 29 de fevereiro. O resultado foi uma exceção que caiu direto em produção. A solução que eu adotei foi abandonar a divisão por 365 e usar diretamente a comparação de datas. Criei uma função que recebe duas datas e retorna a idade baseada na última data de aniversário já ocorrida. Para casos de 29 de fevereiro, tratei separadamente: se a data atual não tem dia 29 de fevereiro no ano corrente, considero o aniversário como tendo ocorrido em 28 de fevereiro ou 1 de março, dependendo da convenção do sistema. Isso eliminou 100% dos erros de boundary condition que eu estava vendo.
👉 Clique no botão abaixo para saber mais sobre o assunto!
O cálculo exato depende do timezone também. Se o usuário nasceu às 23h59 de um dia e você está verificando a idade às 00h01 do dia seguinte em outro fuso horário, a diferença de horas pode mudar o resultado. Eu configurei todos os cálculos para usar UTC e armazenei datas de nascimento sempre na mesma convenção. Isso removeu ambiguidades que causavam discrepâncias de um dia em alguns cenários.
Vieses e armadilhas que ninguém conta
Um problema contra-intuitivo que eu encontrei diz respeito a anos bissextos em cálculos financeiros. Sistemas de aposentadoria e seguros frequentemente usam regras diferentes para calcular idade. Alguns consideram que quem nasce em 29 de fevereiro faz aniversário em 1 de março nos anos normais. Outros usam 28 de fevereiro. A escolha altera o resultado em alguns casos marginais, mas esses casos marginais são justamente os que mais geram disputas e recursos. A outra armadilha que eu vi acontecer várias vezes é com datas mal formatadas. Sistemas que aceitam strings no formato DD/MM/AAAA sem validar strictamente acabam interpretando datas como 13/05/2000 quando na verdade o usuário digitou 05/13/2000 achando que era formato americano. O erro se propagou por meses sem ninguém perceber porque os valores pareciam válidos. Eu resolvi isso impondo validação de formato antes de qualquer cálculo e usando parseadores que rejeitam datas ambíguas em vez de adivinhar.
A desvantagem principal de qualquer abordagem baseada em comparação de datas é a complexidade crescente quando você precisa lidar com calendários históricos. O Brasil adotou o calendário gregoriano em 1890, mas territórios que hoje fazem parte do país usavam o juliano até então. Se você precisa calcular idades de pessoas nascidas antes dessa data, a diferença de 11 dias precisa ser considerada. A maioria dos sistemas ignora isso porque raramente aparece, mas quando aparece o erro é grosseiro: uma idade errada por quase um ano completo. Se você precisa apenas saber quantos anos tem algo simples, como a versão de um software lançado em determinado ano, a conta direta funciona. Ano atual menos ano de lançamento. Mas para dados demográficos, jurídicos ou financeiros, a abordagem ingênua tem taxa de erro significativa em bordas do calendário. O ganho em velocidade de implementação é rápido, mas o custo de correção posterior geralmente compensa não valer a pena o atalho.