Pridėti mėnesius prie datos yra sunkiau, nei atrodo
Pridėti 7 dienas prie datos paprasta. Tiesiog pridedate 7 — ir viskas. Pridėti mėnesį yra visai kitas uždavinys.
Problema ta, kad mėnesiai turi skirtingą dienų skaičių. Sausis turi 31 dieną. Vasaris — 28, kartais 29. Jei esate sausio 31‑ąją ir pridedate vieną mėnesį, gaunate vasario 31‑ąją — kurios nėra.
Kiekviena kalendoriaus biblioteka, skaičiuoklė ir duomenų bazė turi savo nuomonę, ką daryti toliau.
Ką daro dauguma įrankių
Dažniausias elgesys — „priklijuoti“ datą prie paskutinės tikslo mėnesio dienos. Sausio 31 + 1 mėnuo = vasario 28 (arba 29 keliamaisiais metais). Kovo 31 + 1 mėnuo = balandžio 30.
Tai vadinama mėnesio pabaigos apribojimu (end-of-month clamping) ir taip pagal nutylėjimą elgiasi Excel, Google Sheets, Python dateutil ir dauguma datų bibliotekų.
Tai logiška, bet turi subtilią problemą: operacija nėra grįžtama. Jei prie sausio 31 pridedate vieną mėnesį, gaunate vasario 28. Jei tada atimate vieną mėnesį, gaunate sausio 28 — ne sausio 31. „Praradote“ tris dienas.
Perpildymo (overflow) metodas
Kai kurios sistemos leidžia datai „perbėgti“ į kitą mėnesį vietoje apribojimo. Sausio 31 + 1 mėnuo = kovo 3 (arba kovo 2 keliamaisiais metais, nes vasaris turi 29 dienas).
Taip išsaugomas bendras dienų skaičius, bet rezultatas atsiduria visai kitame mėnesyje nei tikėjotės. Tai nustebina ir iš vartotojo perspektyvos dažniausiai yra neteisinga.
Kai kurios duomenų bazės su SQL INTERVAL sintakse gali elgtis taip priklausomai nuo konfigūracijos. Jei nežinote, kokį elgesį naudojate, labai lengva „nudegti“.
Pridėti metus turi tą pačią problemą
Vasario 29 egzistuoja tik keliamaisiais metais. Pridėkite vienus metus prie 2024‑02‑29 ir gausite 2025‑02‑29 — kurios nėra. Apribojimo metodas duos 2025‑02‑28.
Tas pats elgesys, tie patys kompromisai.
Kada tai iš tiesų sukelia klaidų
Klasikinis pavyzdys — prenumeratų atsiskaitymai. Vartotojas užsiregistruoja sausio 31. Kitas apmokėjimas — vasario 28. Tada kovo 28. Tada balandžio 28. Po pirmo mėnesio kiekvieną mėnesį jis apmokestinamas 2–3 dienomis anksčiau nei tikėtųsi.
Pasikartojantys kalendoriaus įvykiai turi tą pačią bėdą. „Kiekvieno mėnesio 31‑ąją“ tyliai virsta „kiekvieno mėnesio paskutinę dieną“ mėnesiams, kurie neturi 31 dienos.
Paskolų grąžinimo grafikai, atlyginimų datos ir bet kas su „mėnesiniu“ pasikartojimu anksčiau ar vėliau susidurs su šiuo kraštiniu atveju.
Pridėti dienas šios problemos neturi
Jei norite išreikšti „po 30 dienų“, o ne „po vieno mėnesio“, tiesiog pridėkite 30 dienų. Rezultatas bus vienareikšmis ir grįžtamas.
Skirtumas svarbus: 30 dienų atsiskaitymo ciklas ir mėnesinis atsiskaitymo ciklas nėra tas pats, ir laikui bėgant jie greitai išsiskiria.
Ką patikrinti savo įrankyje ar bibliotekoje
Prieš pasikliaudami datų pridėjimu bet kurioje sistemoje, verta žinoti:
- Ar ji apriboja, ar leidžia perpildymą mėnesio pabaigos datoms?
- Ar ji išlaiko mėnesio dieną per kelis pridėjimus, ar kiekvieną kartą iš naujo „apriboja“?
- Kas nutinka keliamųjų metų kraštiniais atvejais, pvz., vasario 29 + 1 metai?
Datos skaičiuotuvas parodo tikslų rezultatą bet kuriai datai ir poslinkiui — naudinga greitam patikrinimui prieš įtvirtinant skaičiavimą kode.


