- COMP.CS.140
- 5. Periytyminen
- 5.6 ⌛⌛ Päivämäärät
⌛⌛ Päivämäärät¶
Aseta vastauksesi tiedostoon Dates.java kansiossa Round5/dates.
Toteuta päivämäärien erotuksia laskeva apuluokka Dates
, jolla on alla kuvatut ominaisuudet.
Sisäinen julkinen staattinen luokka
DateDiff
, joka tallettaa alkupäivämääränstart
ja loppupäivämääränend
merkkijonoina sekä päivämäärien välisen erotuksendiff
kokonaislukuna.Julkiset jäsenfunktiot
String getStart()
,String getEnd()
jaint getDiff()
, jotka palauttavat edellämainitut kolme tietoa.Alku- ja loppupäivämäärä palautetaan ISO-8601 -muodossa “vuosi-kuukausi-päivä” eli esim. päivämäärä 6.12.2021 esitettäisiin merkkijonona “
2021-12-06
”.
Kaikki rakentimet (tuskin tarvitset enempää kuin yhden) yksityisiä!
Efekti:
DateDiff
-olioita voi luoda vain luokanDates
puitteissa;Dates
-luokalla on pääsy sisäisen luokkansaDateDiff
yksityisiin jäseniin.
Julkinen jäsenfunktio
String toString()
, joka palauttaa muotoa “start --> end: diff
days” tai “start --> end: 1 day
” olevan merkkijonon, missä sekä alku- että loppupäivämäärä on esitetty muodossa “Weekday päivä.kuukausi.vuosi”. Edellä “Weekday”, koska se esitetään tässä tehtävässä englanniksi.Esimerkiksi jos
DateDiff
-oliondd
alkupäivämäärä olisi 1.1.1999 ja loppupäivämäärä 1.1.2001, niin:dd.getStart()
palauttaisi “1999-01-01
”,dd.getEnd()
palauttaisi “2001-01-01
” jadd.toString()
palauttaisi “Friday 01.01.1999 --> Monday 01.01.2001: 731 days
”.Viikonpäivä esitetään yksinkertaisuuden vuoksi tässä aina englanniksi.
Julkinen staattinen funktio
DateDiff[] dateDiffs(String ...dateStrs)
, joka palauttaa saamiensa päivämäärien väliset erotukset kuvaavatDateDiff
-oliot taulukkona. Erotus lasketaan päivämäärien välisinä päivinä. Esimerkiksi peräkkäisten päivämäärien 3.5.2021 ja 4.5.2021 erotus on 1, ja keskenään samojen päivämäärien erotus on 0.Tarkemmin ottaen funktio lajittelee saamansa päivämäärät aikajärjestykseen, ja palauttaa kutakin kahta järjestyksessä peräkkäistä päivämäärää kohden yhden
DateDiff
-olion. Tämä tulee selväksi tehtävän lopun esimerkeistä.Muistutus: vaihtelevan määrän hyväksyvä parametri
dataStrs
→ funktio saa parametrindateStrs
String
-taulukkona.Kukin taulukon
dateStrs
merkkijono saa esittää päivämäärän joko ISO-8601 -muodossa tai suomalaisessa muodossa “päivä.kuukausi.vuosi”. ISO-8601 -muodossa on oltava päivä ja kuukausi kahdella numerolla ja vuosi neljällä. Funktio hyväksyy suomalaisen päivämäärän, jos päivä ja kuukausi on esitetty yhdellä tai kahdella numerolla (saa olla sekaisinkin) ja vuosi neljällä. Päivämäärien tulee lisäksi olla laillisia; esimerkiksi oikeaa muotoa olevat merkkijonot “2001-02-29
” tai “10.13.2004
” hylättäisiin, koska ne esittävät laittomia päivämääriä.Kukin väärin muotoiltu tai laitonta päivämäärää esittävä merkkijono
dateStr
sivuutetaan, ja sellaisten kohdalla tulostetaan viesti “The datedateStr
is illegal!”.Funktion tulee ensin käydä
dateStrs
läpi ja ottaa niistä talteen vain lailliset päivämäärät. Sen jälkeen lailliset päivämäärät lajitellaan ja kullekin peräkkäiselle parille muodostetaan niitä vastaavaDateDiff
-olio.Vaatimus nelinumeroisesta vuodesta tarkoittaa, että vain välin 1000…9999 vuodet hyväksytään.
Huomaa, että
DateDiff
-oliot palautetaan tavallisessa taulukossa. Jos funktio saa vähemmän kuin 2 laillista päivämäärää (eli yhtäänDateDiff
-oliota ei voi järkevästi muodostaa), palautetaan tyhjä taulukko. Sellaisenkin voi luoda tavalliseen tapaan eli vaikkapanew DateDiff[0]
tai käyttäen tyhjää alustusarvoa{}
.
Muutama vinkki
Päivämäärän laillisuuden tarkistaminen: miten LocalDate.of käyttäytyy, jos päivämäärä on laiton?
Viikonpäivä? LocalDate
-olio tietää esittämänsä päivämäärän viikonpäivän.
Kahden päivämäärän välisen erotuksen laskenta? Eräs kohtalaisen suoraviivainen vaihtoehto on funktio LocalDate.until.
Päivämäärien muotoilun (esim. englanninkieliset viikonpäivien nimet) voi toki toteuttaa itse.
Mutta jos haluat hyödyntää Javan valmiita apuvälineitä päivämäärän esittämiseen, esim. luokka
DateTimeFormatter
yhdessä localen Locale.US
kanssa voisi sopia tähän tehtävään.
Esimerkkitestejä¶
Automaattiset testit testaavat luokan Dates
toteutustasi suunnilleen seuraavanlaisella
testiohjelmalla:
public class DatesTest {
public static void main(String args[]) {
Dates.DateDiff[] diffArray = {};
if(args.length == 2) {
diffArray = Dates.dateDiffs(args[0], args[1]);
}
else {
diffArray = Dates.dateDiffs(args);
}
for(Dates.DateDiff dd : diffArray) {
System.out.format("start: %s end: %s diff: %d%n",
dd.getStart(), dd.getEnd(), dd.getDiff());
System.out.println(" " + dd);
}
}
}
Alla on kuvattu esimerkiksi kolme testiohjelman suoritusta odotettuine tuloksineen:
java DatesTest 1.1.2022 5.6.850
The date "5.6.850" is illegal!
java DatesTest 2022-05-31 1.1.2022
start: 2022-01-01 end: 2022-05-31 diff: 150
Saturday 01.01.2022 --> Tuesday 31.05.2022: 150 days
java DatesTest 1.08.2016 07.3.2004 31.05.2022 29.2.2015 2017-11-23 7.04.2019 2000-3-6 2009-05-13
The date "29.2.2015" is illegal!
The date "2000-3-6" is illegal!
start: 2004-03-07 end: 2009-05-13 diff: 1893
Sunday 07.03.2004 --> Wednesday 13.05.2009: 1893 days
start: 2009-05-13 end: 2016-08-01 diff: 2637
Wednesday 13.05.2009 --> Monday 01.08.2016: 2637 days
start: 2016-08-01 end: 2017-11-23 diff: 479
Monday 01.08.2016 --> Thursday 23.11.2017: 479 days
start: 2017-11-23 end: 2019-04-07 diff: 500
Thursday 23.11.2017 --> Sunday 07.04.2019: 500 days
start: 2019-04-07 end: 2022-05-31 diff: 1150
Sunday 07.04.2019 --> Tuesday 31.05.2022: 1150 days
A+ esittää tässä kohdassa tehtävän palautuslomakkeen.