Skip to content

Methodology

Metodologia de cálculo de idade

Empréstimo com consciência do calendário, não divisão simples. O erro de 4 dias que código ingênuo acumula.

By Published

Calcular a idade em anos-meses-dias parece trivial. Não é. A abordagem ingênua de “hoje menos o aniversário dividido por 365,25” desvia cerca de um dia a cada quatro a sete anos porque anos reais não têm um número constante de dias. O algoritmo correto usa empréstimo de calendário — a mesma lógica da subtração ensinada na escola, mas com “dígitos” de comprimento variável.

O algoritmo de empréstimo de mês

Dado uma data de nascimento (bY-bM-bD) e hoje (tY-tM-tD):

  1. Diferença de ano: tY − bY.
  2. Diferença de mês: tM − bM. Se negativa, empreste 1 do contador de anos: subtraia 1 da diferença de anos, adicione 12 à diferença de meses.
  3. Diferença de dia: tD − bD. Se negativa, empreste 1 do contador de meses: subtraia 1 da diferença de meses, adicione o comprimento do mês anterior à diferença de dias.

A etapa 3 é onde a maioria das implementações erra. O “comprimento do mês anterior” não é uma constante 30 — é 28, 29, 30 ou 31, dependendo do mês e (para fevereiro) do ano.

Exemplo prático

Nascimento: 31/12/1990. Hoje: 15/03/2026.

  1. Diferença de anos: 2026 − 1990 = 36.
  2. Diferença de meses: 3 − 12 = −9. Empréstimo: diferença de anos vai para 35, diferença de meses vai para 3.
  3. Diferença de dias: 15 − 31 = −16. Empréstimo: diferença de meses vai para 2, diferença de dias += comprimento do mês anterior. O mês anterior é fevereiro de 2026 (28 dias, não é ano bissexto). Diferença de dias = −16 + 28 = 12.

Resultado: 35 anos, 2 meses, 12 dias.

O truque do comprimento do mês anterior

A forma mais limpa de perguntar “quantos dias teve o mês anterior?” em JavaScript:

new Date(year, month, 0).getDate()
// Retorna o último dia do (mês - 1).
// O dia 0 do mês N é interpretado como o último dia do mês N-1.

Isso trata a correção de anos bissextos do fevereiro automaticamente porque o Date já sabe. new Date(2024, 2, 0).getDate() retorna 29; new Date(2023, 2, 0).getDate() retorna 28.

Aniversários em anos bissextos (29 de fevereiro)

Pessoas nascidas em 29 de fevereiro levantam uma questão recorrente: qual é o seu aniversário em anos não bissextos? Duas convenções:

  • Deslocar para 1º de março — padrão no Reino Unido e Hong Kong.
  • Deslocar para 28 de fevereiro — padrão nos EUA, Taiwan e Nova Zelândia. A calculadora usa essa convenção.

A escolha afeta quando o momento “você completou N anos” acontece em anos não bissextos. Para a maioria dos propósitos não importa — a data de nascimento subjacente ainda é 29 de fevereiro e a diferença é de um dia por ano não bissexto.

Por que “dias / 365,25” diverge

365,25 é a duração média de um ano ao longo de um ciclo gregoriano de 400 anos. Qualquer ano individual tem 365 ou 366 dias. Em janelas curtas, a média não é uma boa aproximação:

  • 4 anos contêm exatamente 1 ano bissexto → 1461 dias → 365,25 exatamente. Correto.
  • O desvio vem da regra do século: 1900 não foi um ano bissexto (divisível por 100, mas não por 400). 2000 foi. Calcular idades que abrangem 1900 ou 2100 com a aproximação de 365,25 produz erros visíveis em nível de dias.

Para cálculo de idade, o empréstimo de calendário é sempre exato. A aproximação ingênua serve para cálculos rápidos, mas é incorreta para qualquer coisa que precise corresponder a um passaporte ou certidão de nascimento.

Implementação de referência do algoritmo

function age(birth: Date, today: Date) {
  let y = today.getFullYear() - birth.getFullYear();
  let m = today.getMonth() - birth.getMonth();
  let d = today.getDate() - birth.getDate();
  if (d < 0) {
    const prevMonthLen = new Date(today.getFullYear(), today.getMonth(), 0).getDate();
    d += prevMonthLen;
    m -= 1;
  }
  if (m < 0) {
    m += 12;
    y -= 1;
  }
  return { years: y, months: m, days: d };
}

O algoritmo é executado em tempo O(1) sem divisão, sem aritmética de ponto flutuante e sem bibliotecas de calendário. O único desvio orientado por especificação é o tratamento do ano bissexto — e mesmo isso é delegado aoDate, que implementa a regra gregoriana do ECMA-262.

Pressupostos e limitações

  • Apenas calendário gregoriano. Calendários Hijri, Hebraico, Lunar Chinês e Juliano precisam de algoritmos diferentes; o conversor não expõe seleção de sistema de calendário.
  • Apenas data, não data-hora. As entradas são truncadas para meia-noite no fuso horário local do usuário. Transições de horário de verão não afetam o resultado.
  • 29 de fev → 28 de fev.Usamos a convenção dos EUA por padrão. Usuários no Reino Unido e Hong Kong devem adicionar um dia ao marcador “você completou N anos” em anos não bissextos.
  • Sem suporte a datas anteriores à adoção do calendário gregoriano. Datas anteriores a 15/10/1582 usam a extensão gregoriana proleptica — historicamente, estas teriam sido registradas como datas Julianas com diferença de 10 a 13 dias.
  • Sem tratamento de segundos intercalares. Segundos intercalares não afetam a aritmética de datas do calendário.
  • Datas futuras retornam zero, não negativo. Uma idade negativa quase sempre é um erro de interface do usuário, não um resultado legítimo.

Frequently asked questions

Como o Convertitive calcula a idade em anos, meses e dias?
Usamos um algoritmo de empréstimo de calendário: calculamos a diferença bruta em anos, meses e dias e, quando um componente fica negativo, tomamos emprestado da unidade de maior ordem. O empréstimo de dias usa o comprimento exato do mês anterior (28, 29, 30 ou 31 dias), obtido via Date(year, month, 0).getDate() do JavaScript para que a correção do fevereiro em anos bissextos seja automática.
Por que o Convertitive não usa dias / 365,25 para calcular a idade?
365,25 é a duração média do ano ao longo de um ciclo gregoriano completo de 400 anos, mas qualquer ano individual tem exatamente 365 ou 366 dias. Usar a média produz um desvio de ~1 dia a cada alguns anos e um erro visível quando o intervalo de datas abrange um século como 1900 (não é ano bissexto) ou 2100. O algoritmo de empréstimo é O(1), não tem aritmética de ponto flutuante e é sempre exato.
O que acontece com aniversários em 29 de fevereiro em anos não bissextos?
O Convertitive desloca o dia 29 de fevereiro para o dia 28 de fevereiro por padrão — a convenção dos EUA, Taiwan e Nova Zelândia. A convenção do Reino Unido e de Hong Kong desloca para 1º de março (segundo a Lei de Registro de Nascimentos e Óbitos de 1953). As duas convenções diferem em um dia em anos não bissextos; nenhuma é universalmente correta.
Qual sistema de calendário a calculadora assume?
Apenas gregoriano proléptico — a regra de ano bissexto da reforma Inter Gravissimas de 1582 (divisível por 4, exceto séculos, exceto múltiplos de 400). Entradas em calendários Hijri, Hebraico, Lunar Chinês e Juliano não são suportadas. Datas anteriores a 15/10/1582 usam a extensão gregoriana proleptica, que difere das datas Julianas registradas em 10 a 13 dias.
Uma transição de horário de verão afeta o resultado da idade?
Não. A calculadora opera em datas do calendário, não em timestamps. As entradas são tratadas como meia-noite local sem componente de hora, portanto nenhuma transição de horário de verão altera a contagem de dias.

Related

Published May 15, 2026