Skip to content

Methodology

Metodología de cálculo de edad

Préstamo con conciencia del calendario, no división ingenua. El error de 4 días que acumula el código ingenuo.

By Published

Calcular la edad en años-meses-días parece trivial. No lo es. El enfoque ingenuo de «hoy menos el cumpleaños dividido por 365.25» se desvía aproximadamente un día cada cuatro a siete años porque los años reales no tienen un número constante de días. El algoritmo correcto usa préstamo de calendario: la misma lógica que la resta de la escuela primaria pero con «dígitos» de longitud variable.

El algoritmo de préstamo de mes

Dada una fecha de nacimiento (nA-nM-nD) y hoy (hA-hM-hD):

  1. Diferencia de años: hA − nA.
  2. Diferencia de meses: hM − nM. Si es negativa, tomar prestado 1 del conteo de años: restar 1 de la diferencia de años, sumar 12 a la diferencia de meses.
  3. Diferencia de días: hD − nD. Si es negativa, tomar prestado 1 del conteo de meses: restar 1 de la diferencia de meses, sumar la longitud del mes anterior a la diferencia de días.

El paso 3 es donde la mayoría de las implementaciones fallan. La «longitud del mes anterior» no es una constante 30: es 28, 29, 30 o 31 dependiendo del mes y (para febrero) del año.

Ejemplo resuelto

Nacimiento: 1990-12-31. Hoy: 2026-03-15.

  1. Diferencia de años: 2026 − 1990 = 36.
  2. Diferencia de meses: 3 − 12 = −9. Préstamo: la diferencia de años baja a 35, la diferencia de meses pasa a 3.
  3. Diferencia de días: 15 − 31 = −16. Préstamo: la diferencia de meses baja a 2, la diferencia de días += longitud del mes anterior. El mes anterior es febrero de 2026 (28 días, no es año bisiesto). Diferencia de días = −16 + 28 = 12.

Resultado: 35 años, 2 meses, 12 días.

El truco de la longitud del mes anterior

La forma más limpia de preguntar «¿cuántos días tenía el mes anterior?» en JavaScript:

new Date(year, month, 0).getDate()
// Devuelve el último día de (month - 1).
// El día 0 del mes N se interpreta como el último día de N-1.

Esto maneja automáticamente la corrección de años bisiestos en febrero porque Date lo sabe. new Date(2024, 2, 0).getDate() devuelve 29; new Date(2023, 2, 0).getDate() devuelve 28.

Cumpleaños en año bisiesto (29 de febrero)

Las personas nacidas el 29 de febrero plantean una pregunta recurrente: ¿cuál es su cumpleaños en años no bisiestos? Dos convenciones:

  • Trasladar al 1 de marzo — convención por defecto en el Reino Unido y Hong Kong.
  • Trasladar al 28 de febrero — convención por defecto en EE. UU., Taiwán y Nueva Zelanda. La calculadora usa esta opción.

La elección afecta al momento en que ocurre el «cumpliste N años» en años no bisiestos. Para la mayoría de los propósitos no importa: la fecha de nacimiento subyacente sigue siendo el 29 de febrero y la diferencia es de un día por año no bisiesto.

Por qué «días / 365.25» se desvía

365.25 es la longitud promedio de un año en un ciclo gregoriano de 400 años. Cualquier año individual es 365 o 366. En ventanas cortas el promedio no es una buena aproximación:

  • 4 años contienen exactamente 1 año bisiesto → 1461 días → 365.25 exactamente. Correcto.
  • 3 años desde el 1 de marzo de 2021 → 1095 días. Dividido por 365.25 = 2.998… → redondeado, 3 años. Correcto.
  • La desviación viene de la regla del siglo: 1900 no fue año bisiesto (divisible por 100, no por 400). 2000 sí lo fue. Calcular edades que abarcan 1900 o 2100 con la aproximación de 365.25 produce errores visibles a nivel de día.

Para el cálculo de edad, el préstamo de calendario es siempre exacto. La aproximación ingenua está bien para cálculos aproximados, pero es incorrecta para cualquier cosa que deba coincidir con un pasaporte o partida de nacimiento.

Detalles del algoritmo: préstamo de mes completo

La implementación de referencia completa es lo suficientemente corta para reproducirla en línea; la sorpresa es cuántas pocas ramas necesita una vez que el truco del día 0 resuelve el problema de longitud de mes variable.

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) {
    // Tomar días prestados del mes anterior — el día 0 devuelve el último día del mes anterior.
    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 };
}

El algoritmo se ejecuta en tiempo O(1) sin divisiones, sin aritmética de punto flotante y sin bibliotecas de calendario. La única rama impulsada por especificaciones es el manejo de años bisiestos, y eso se delega a Date, que implementa la regla gregoriana (cada año divisible por 4 excepto años de siglo no divisibles por 400) según ECMA-262.

Comparación con el enfoque naive de conteo de días para un intervalo de 100 años:

MétodoResultado para 1925-01-01 → 2025-01-01Error
Algoritmo de préstamo100 a, 0 m, 0 d0 d (exacto)
(días) / 365.2599.9999 a → redondea a 99~1 d (error silencioso)
(días) / 365100.07 a~25 d

Fuentes y referencias

La regla de año bisiesto proviene de la reforma gregoriana original de 1582 (Inter Gravissimas); el formato de fecha que aceptamos es ISO 8601; el truco de la longitud del mes anterior es un comportamiento ECMAScript bien definido de ECMA-262. Las convenciones de traslado del cumpleaños del 29 de febrero son específicas de cada jurisdicción y se remontan a la legislación nacional: consulte nuestra guía de métodos de cálculo de edad para la tabla jurisdiccional. El Reino Unido y Hong Kong trasladan al 1 de marzo según la Ley de Registro de Nacimientos y Defunciones de 1953; EE. UU., Nueva Zelanda y Taiwán usan el 28 de febrero por convención administrativa.

Supuestos y limitaciones

  • Solo calendario gregoriano. Los calendarios Hijri, hebreo, lunar chino y juliano necesitan algoritmos diferentes; el conversor no expone la selección del sistema de calendario.
  • Solo fecha, no fecha-hora. Las entradas se truncan a medianoche en la zona horaria local del usuario. Los cambios de horario de verano no afectan al resultado.
  • 29 de febrero → 28 de febrero. Usamos la convención de EE. UU. por defecto. Los usuarios en jurisdicciones de Reino Unido/Hong Kong deben añadir un día al marcador «cumpliste N años» en años no bisiestos.
  • Sin soporte antes de la adopción gregoriana. Las fechas de nacimiento anteriores a 1582-10-15 usan la extensión gregoriana proléctica: históricamente habrían sido registradas como fechas julianas y desplazadas 10-13 días hacia adelante para la comparación moderna.
  • Sin manejo de segundos intercalares. Los segundos intercalares no afectan a la aritmética de días de calendario; si necesita precisión UTC frente a TAI, use una herramienta diferente.
  • Las fechas futuras devuelven cero, no negativo. Una edad negativa casi siempre es un error de interfaz de usuario y no un resultado legítimo.

Casos extremos que gestiona la calculadora

  • Fechas de nacimiento futuras — devolvemos cero en lugar de edades negativas. Una edad negativa es un vector de error.
  • Hoy coincide con la fecha de nacimiento — 0 años, 0 meses, 0 días.
  • A través de transiciones de horario de verano — la calculadora usa solo matemáticas de fecha (sin horas), por lo que los cambios de horario de verano no afectan al resultado.

Frequently asked questions

¿Cómo calcula Convertitive la edad en años, meses y días?
Usamos un algoritmo de préstamo de calendario: calculamos la diferencia bruta en años, meses y días, y luego tomamos prestado de la unidad siguiente cuando un componente resulta negativo. El préstamo de días usa la longitud exacta del mes anterior (28, 29, 30 o 31 días), obtenida mediante Date(año, mes, 0).getDate() de JavaScript, de modo que la corrección de años bisiestos en febrero se gestiona automáticamente.
¿Por qué Convertitive no usa días / 365.25 para calcular la edad?
365.25 es la longitud promedio del año en el ciclo gregoriano de 400 años, pero cualquier año individual tiene exactamente 365 o 366 días. Usar el promedio produce una desviación de ~1 día cada pocos años y un error visible cuando el rango de fechas abarca un año centenario como 1900 (no bisiesto) o 2100. El algoritmo de préstamo es O(1), no tiene aritmética de punto flotante y siempre es exacto.
¿Qué ocurre con los cumpleaños del 29 de febrero en años no bisiestos?
Convertitive traslada el 29 de febrero al 28 de febrero por defecto, que es la convención de EE. UU., Taiwán y Nueva Zelanda. La convención del Reino Unido y Hong Kong lo traslada al 1 de marzo (según la Ley de Registro de Nacimientos y Defunciones de 1953). Las dos convenciones difieren en un día en años no bisiestos; ninguna convención es universalmente correcta.
¿Qué sistema de calendario asume la calculadora?
Solo gregoriano proléptico: la regla de año bisiesto de la reforma Inter Gravissimas de 1582 (divisible por 4, excepto siglos, excepto siglos divisibles por 400). Las entradas en calendario Hijri, hebreo, lunar chino y juliano no son compatibles. Las fechas anteriores a 1582-10-15 usan la extensión gregoriana proléctica, que difiere de las fechas julianas registradas entre 10 y 13 días.
¿Afecta un cambio de horario de verano al resultado de la edad?
No. La calculadora opera con fechas de calendario, no con marcas de tiempo. Las entradas se tratan como medianoche local sin componente de tiempo, por lo que ningún cambio de horario de verano altera el conteo de días.

Related

Published May 15, 2026