Aggiungere mesi a una data è più complicato di quanto sembri

Aggiungere 7 giorni a una data è semplice. Prendi un numero, aggiungi 7, fatto. Aggiungere un mese è un problema completamente diverso.

Il problema è che i mesi hanno lunghezze diverse. Gennaio ha 31 giorni. Febbraio ne ha 28, a volte 29. Se sei il 31 gennaio e aggiungi un mese, arrivi al 31 febbraio — che non esiste.

Ogni libreria di calendari, foglio di calcolo e database ha un'opinione su cosa fare dopo.

Quello che fa la maggior parte dei tool

Il comportamento più comune è arrotondare all'ultimo giorno del mese di destinazione. 31 gennaio + 1 mese = 28 febbraio (o 29 in un anno bisestile). 31 marzo + 1 mese = 30 aprile.

Questo si chiama clamping di fine mese ed è quello che fanno Excel, Google Sheets, dateutil di Python e la maggior parte delle librerie di date per impostazione predefinita.

È sensato, ma crea un problema sottile: l'operazione non è reversibile. Se aggiungi un mese al 31 gennaio, ottieni il 28 febbraio. Se poi sottrai un mese, ottieni il 28 gennaio — non il 31 gennaio. Hai perso tre giorni.

L'approccio dell'overflow

Alcuni sistemi lasciano che la data trabocchi nel mese successivo invece di arrotondare. 31 gennaio + 1 mese = 3 marzo (o 2 marzo in un anno bisestile, poiché febbraio ha 29 giorni).

Questo preserva il conteggio totale dei giorni, ma il risultato finisce in un mese completamente diverso da quello che intendevi. È sorprendente e solitamente sbagliato dal punto di vista dell'utente.

La sintassi INTERVAL di SQL in alcuni database fa questo a seconda della configurazione. È facile bruciarsi se non sei consapevole di quale comportamento stai usando.

Aggiungere anni ha lo stesso problema

Il 29 febbraio esiste solo negli anni bisestili. Aggiungi un anno al 29 febbraio 2024 e ottieni il 29 febbraio 2025 — che non esiste. L'arrotondamento ti dà il 28 febbraio 2025.

Stesso comportamento, stessi compromessi.

Quando questo causa effettivamente bug

La fatturazione di abbonamenti è l'esempio classico. Un utente si iscrive il 31 gennaio. La sua prossima data di fatturazione è il 28 febbraio. Poi il 28 marzo. Poi il 28 aprile. Ogni mese dopo il primo, vengono fatturati 2-3 giorni prima di quanto si aspetterebbero.

Gli eventi ricorrenti del calendario hanno lo stesso problema. "Ogni mese il 31" diventa silenziosamente "ogni mese l'ultimo giorno" per i mesi che non arrivano al 31.

I calendari di rimborso dei prestiti, le date di stipendio e tutto ciò che ha ricorrenza "mensile" prima o poi incappa in questo caso limite.

Aggiungere giorni non ha questo problema

Se hai bisogno di esprimere "30 giorni da ora" piuttosto che "un mese da ora", aggiungi semplicemente 30 giorni. Il risultato è inequivocabile e reversibile.

La distinzione è importante: un ciclo di fatturazione di 30 giorni e uno mensile non sono la stessa cosa e divergono rapidamente nel tempo.

Cosa controllare nel tuo tool o libreria

Prima di affidarti all'aggiunta di date in qualsiasi sistema, vale la pena sapere:

  • Arrotonda o fa overflow per le date di fine mese?
  • Preserva il giorno del mese attraverso aggiunte multiple, o arrotonda ogni volta?
  • Per i casi limite degli anni bisestili, cosa succede il 29 feb + 1 anno?

Il Date Calculator ti mostra il risultato esatto per qualsiasi data e offset — utile per verificare prima di impegnarti in un calcolo nel codice.

Articoli correlati