Kuukausien lisääminen päivämäärään on vaikeampaa kuin miltä se kuulostaa

Päivämäärään 7 päivän lisääminen on helppoa. Otat luvun, lisäät 7, ja olet valmis. Kuukauden lisääminen on täysin eri ongelma.

Ongelma on siinä, että kuukausilla on eri pituudet. Tammikuussa on 31 päivää. Helmikuussa on 28, joskus 29. Jos olet 31. tammikuuta ja lisäät yhden kuukauden, päädy 31. helmikuuhun — jota ei ole olemassa.

Jokaisella kalenterikirjastolla, taulukkolaskentaohjelmalla ja tietokannalla on oma mielipide siitä, mitä seuraavaksi tehdään.

Mitä useimmat työkalut tekevät

Yleisin käyttäytyminen on siirtää päivämäärä kohde­kuukauden viimeiseen päivään. 31. tammikuuta + 1 kuukausi = 28. helmikuuta (tai 29 karkaus­vuonna). 31. maaliskuuta + 1 kuukausi = 30. huhtikuuta.

Tätä kutsutaan kuukauden lopun rajaamiseksi, ja näin toimivat Excel, Google Sheets, Pythonin dateutil ja useimmat pääivä­kirjastot oletuksena.

Se on järkevää, mutta aiheuttaa hienovaraisen ongelman: operaatio ei ole käännettävissä. Jos lisäät yhden kuukauden 31. tammikuuhun, saat 28. helmikuuta. Jos sitten vähennät yhden kuukauden, saat 28. tammikuuta — et 31. tammikuuta. Olet menettänyt kolme päivää.

Ylivuoto-lähestymistapa

Jotkut järjestelmät antavat päivämäärän ylivuotaa seuraavaan kuukauteen rajoittamisen sijaan. 31. tammikuuta + 1 kuukausi = 3. maaliskuuta (tai 2. maaliskuuta karkaus­vuonna, koska helmikuulla on 29 päivää).

Tämä säilyttää päivien kokonaismäärän, mutta tulos päätyy täysin eri kuukauteen kuin aiot. Se on yllättävää ja yleensä väärää käyttäjän näkökulmasta.

SQL:n INTERVAL-syntaksi joissakin tietokannoissa toimii näin riippuen asetuksista. On helppo joutua pulaan, jos et ole tietoinen siitä, kumpi käyttäytyminen on käytössä.

Vuosien lisäämisellä on sama ongelma

29. helmikuuta on olemassa vain karkaus­vuosina. Lisää yksi vuosi 29. helmikuuhun 2024 ja saat 29. helmikuuta 2025 — jota ei ole olemassa. Rajaaminen antaa sinulle 28. helmikuuta 2025.

Sama käyttäytyminen, samat kompromissit.

Milloin tämä aiheuttaa todellisia virheitä

Tilaus­laskutus on klassinen esimerkki. Käyttäjä rekisteröityy 31. tammikuuta. Hänen seuraava laskutus­päivänsä on 28. helmikuuta. Sitten 28. maaliskuuta. Sitten 28. huhtikuuta. Jokaisen kuukauden jälkeen ensimmäistä, hänelle laskutetaan 2–3 päivää aikaisemmin kuin hän odottaisi.

Toistuvilla kalenteritapahtumilla on sama ongelma. "Joka kuukausi 31. päivänä" hiljaisen hiljaa muuttuu "joka kuukauden viimeisenä päivänä" kuukauksille, joilla ei ole 31. päivää.

Lainan takaisinmaksu­aikataulut, palkka­päivät ja kaikki kuukausittaisella toistolla tehdyt asiat törmäävät lopulta tähän raja­tapaukseen.

Päivien lisäämisellä ei ole tätä ongelmaa

Jos haluat ilmaista "30 päivää tästä päivästä" sen sijaan että "yksi kuukausi tästä päivästä", lisää vain 30 päivää. Tulos on yksiselitteinen ja käännettävissä.

Ero on tärkeä: 30 päivän laskutus­sykli ja kuukausi­laskutus­sykli eivät ole sama asia, ja ne eroavat toisistaan nopeasti ajan mittaan.

Mitä tarkistaa omasta työkalustasi tai kirjastostasi

Ennen kuin luotat päivämäärän lisäämiseen missään järjestelmässä, kannattaa tietää:

  • Rajaaako vai ylivuotaako se kuukauden lopun päivämäärissä?
  • Säilyttääkö se päivän numeroa useiden lisäysten yli vai rajaako se uudelleen joka kerta?
  • Karkaus­vuoden raja­tapauksissa, mitä tapahtuu 29. helmikuussa + 1 vuosi?

Date Calculator näyttää sinulle tarkan tuloksen mille tahansa päivämäärälle ja siirtymälle — hyödyllinen ennen kuin vahvistat laskennan koodissa.

Aiheeseen liittyvät artikkelit