Methodology
Metodologia del calcolo dell’età
Prestito consapevole del calendario, non semplice divisione. L’errore di 4 giorni che il codice ingenuo accumula.
By Buğra SözeriPublished
Calcolare l’età in anni-mesi-giorni sembra banale. Non lo è. L’approccio ingenuo “oggi meno data di nascita diviso 365,25” deriva di circa un giorno ogni quattro-sette anni perché gli anni reali non hanno un numero costante di giorni. L’algoritmo corretto usa il prestito dal calendario — la stessa logica della sottrazione delle scuole elementari ma con “cifre” di lunghezza variabile.
L’algoritmo di prestito dal mese
Data una data di nascita (bY-bM-bD) e oggi (tY-tM-tD):
- Differenza anni:
tY − bY. - Differenza mesi:
tM − bM. Se negativa, prendi in prestito 1 dal conteggio degli anni: sottrai 1 dalla differenza anni, aggiungi 12 alla differenza mesi. - Differenza giorni:
tD − bD. Se negativa, prendi in prestito 1 dal conteggio dei mesi: sottrai 1 dalla differenza mesi, aggiungi la lunghezza del mese precedente alla differenza giorni.
Il passo 3 è dove la maggior parte delle implementazioni va storta. La “lunghezza del mese precedente” non è una costante 30 — è 28, 29, 30 o 31 a seconda del mese e (per febbraio) dell’anno.
Esempio pratico
Nascita: 1990-12-31. Oggi: 2026-03-15.
- Differenza anni: 2026 − 1990 = 36.
- Differenza mesi: 3 − 12 = −9. Prestito: differenza anni scende a 35, differenza mesi diventa 3.
- Differenza giorni: 15 − 31 = −16. Prestito: differenza mesi scende a 2, differenza giorni += lunghezza del mese precedente. Il mese precedente è febbraio 2026 (28 giorni, non bisestile). Differenza giorni = −16 + 28 = 12.
Risultato: 35 anni, 2 mesi, 12 giorni.
Il trucco della lunghezza del mese precedente
Il modo più elegante per chiedere “quanto era lungo il mese precedente?” in JavaScript:
new Date(year, month, 0).getDate() // Restituisce l'ultimo giorno di (month - 1). // Il giorno 0 del mese N viene interpretato come giorno -0 = ultimo giorno di N-1.
Questo gestisce automaticamente la correttezza degli anni bisestili di febbraio perché Date lo sa già. new Date(2024, 2, 0).getDate() restituisce 29; new Date(2023, 2, 0).getDate() restituisce 28.
Compleanni negli anni bisestili (29 feb)
Le persone nate il 29 febbraio pongono una domanda ricorrente: quando è il loro compleanno negli anni non bisestili? Due convenzioni:
- Spostare al 1° marzo — default per UK e Hong Kong.
- Spostare al 28 febbraio — default per USA, Taiwan, Nuova Zelanda. Il calcolatore usa questa convenzione.
La scelta influisce su quando avviene il momento “hai compiuto N anni” negli anni non bisestili. Per la maggior parte degli scopi non ha importanza — la data di nascita sottostante è sempre il 29 feb e la differenza è un giorno per anno non bisestile.
Perché “giorni / 365,25” deriva
365,25 è la lunghezza media di un anno nel ciclo gregoriano di 400 anni. Ogni singolo anno è 365 o 366. Su finestre brevi la media non è una buona approssimazione:
- 4 anni contengono esattamente 1 anno bisestile → 1461 giorni → 365,25 esatti. Corretto.
- Lo scarto viene dalla regola del secolo: il 1900 non era un anno bisestile (divisibile per 100, non per 400). Il 2000 sì. Il calcolo delle età che attraversano il 1900 o il 2100 con l’approssimazione 365,25 produce errori visibili a livello di giorni.
Per il calcolo dell’età, il prestito dal calendario è sempre esatto. L’approssimazione ingenua va bene per calcoli approssimativi ma è sbagliata per qualsiasi cosa che debba corrispondere a un passaporto o a un certificato di nascita.
Dettagli dell’algoritmo: il prestito dal mese completo
L’implementazione di riferimento completa è abbastanza breve da essere riprodotta inline; la sorpresa è quanti pochi rami siano necessari una volta che il trucco del giorno-0 gestisce il problema della lunghezza variabile del mese.
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) {
// Presta giorni dal mese precedente — giorno 0 restituisce l'ultimo giorno del mese precedente.
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 };
}L’algoritmo viene eseguito in tempo O(1) senza divisione, senza aritmetica in virgola mobile e senza librerie di calendario. L’unico ramo guidato dalle specifiche è la gestione degli anni bisestili — e anche quella viene delegata a Date, che implementa la regola gregoriana (ogni anno divisibile per 4 eccetto gli anni del secolo non divisibili per 400) da ECMA-262.
Confronto con l’approccio del conteggio ingenuo dei giorni su un arco di 100 anni:
| Metodo | Risultato per 1925-01-01 → 2025-01-01 | Errore |
|---|---|---|
| Algoritmo di prestito | 100 a, 0 m, 0 g | 0 g (esatto) |
| (giorni) / 365,25 | 99,9999 a → arrotonda a 99 | ~1 g (errore silenzioso) |
| (giorni) / 365 | 100,07 a | ~25 g |
Fonti e riferimenti
La regola degli anni bisestili è la riforma gregoriana originale del 1582 (Inter Gravissimas); il formato data che accettiamo è ISO 8601; il trucco della lunghezza del mese precedente è un comportamento ECMAScript ben definito da ECMA-262. Le convenzioni di spostamento del compleanno del 29 feb sono specifiche della giurisdizione e risalgono alla legislazione nazionale — vedi la nostra guida ai metodi di calcolo dell’età per la tabella giurisdizionale.
Presupposti e limitazioni
- Solo calendario gregoriano. I calendari Hijri, ebraico, lunare cinese e giuliano richiedono algoritmi diversi; il convertitore non espone la selezione del sistema di calendario.
- Solo data, non data-ora.Gli input sono troncati a mezzanotte nel fuso orario locale dell’utente. Le transizioni dell’ora legale non influiscono sul risultato.
- 29 feb → 28 feb come spostamento.Usiamo la convenzione americana per impostazione predefinita. Gli utenti nelle giurisdizioni UK/HK devono aggiungere un giorno al marcatore “hai compiuto N anni” negli anni non bisestili.
- Nessun supporto per date prima dell’adozione gregoriana. Le date di nascita precedenti al 15 ottobre 1582 usano l’estensione gregoriana prolettica — storicamente queste sarebbero state registrate come date giuliane e spostate in avanti di 10-13 giorni per il confronto moderno.
- Nessuna gestione dei secondi intercalari.I secondi intercalari non influiscono sull’aritmetica dei giorni del calendario; se hai bisogno della precisione UTC vs TAI, usa un altro strumento.
- Le date future restituiscono zero, non negativo. Un’età negativa è quasi sempre un bug dell’interfaccia utente piuttosto che un risultato legittimo.
Casi limite gestiti dal calcolatore
- Date di nascita future— restituiamo zero invece di età negative. Un’età negativa è una superficie di bug.
- Oggi uguale alla data di nascita— 0 anni, 0 mesi, 0 giorni.
- Attraverso le transizioni dell’ora legale— il calcolatore usa la matematica solo sulle date (nessun orario), quindi le variazioni dell’ora legale non influiscono sul risultato.
Frequently asked questions
- Come calcola Convertitive l’età in anni, mesi e giorni?
- Usiamo un algoritmo di prestito dal calendario: calcoliamo la differenza grezza in anni, mesi e giorni, poi prendiamo in prestito dall’unità superiore quando un componente diventa negativo. Il prestito dei giorni usa la lunghezza esatta del mese precedente (28, 29, 30 o 31 giorni), ottenuta tramite Date(year, month, 0).getDate() di JavaScript, così la correttezza per i mesi bisestili di febbraio è gestita automaticamente.
- Perché Convertitive non usa giorni / 365,25 per calcolare l’età?
- 365,25 è la lunghezza media di un anno nell’intero ciclo gregoriano di 400 anni, ma ogni singolo anno ha esattamente 365 o 366 giorni. Usare la media produce uno scarto di circa 1 giorno ogni pochi anni e un errore visibile quando l’intervallo attraversa un anno secolare come il 1900 (non bisestile) o il 2100. L’algoritmo di prestito è O(1), non ha aritmetica in virgola mobile ed è sempre esatto.
- Cosa succede con i compleanni del 29 febbraio negli anni non bisestili?
- Convertitive sposta il 29 feb al 28 feb per impostazione predefinita — la convenzione di USA, Taiwan e Nuova Zelanda. La convenzione di UK e Hong Kong sposta al 1° marzo (secondo il Births and Deaths Registration Act del 1953). Le due convenzioni differiscono di un giorno negli anni non bisestili; nessuna convenzione è universalmente corretta.
- Quale sistema di calendario assume il calcolatore?
- Solo il calendario gregoriano prolettico — la regola degli anni bisestili della riforma Inter Gravissimas del 1582 (divisibile per 4, eccetto i secoli, eccetto i secoli divisibili per 400). I calendari Hijri, ebraico, lunare cinese e giuliano non sono supportati. Le date precedenti al 15 ottobre 1582 usano l’estensione gregoriana prolettica, che differisce dalle date giuliane registrate di 10–13 giorni.
- Una transizione dell’ora legale influisce sul risultato dell’età?
- No. Il calcolatore opera su date del calendario, non su timestamp. Gli input sono trattati come mezzanotte locale senza componente oraria, quindi nessuna transizione dell’ora legale modifica il conteggio dei giorni.
Related
Published May 15, 2026