# 3a class Dato3a: # utvides noe fra 3f def __init__(self, å, m, d, dag): self._aar = å self._mnd = m self._dato = d self._dag = dag # 0 for mandag, 1 for tirsdag,... self._ukedag = ukedager[dag] def aaaammdd(self): # str0 returnerer argumentet som string med '0' foran hvis # lengden av argumentet er 1, jf. definisjonen nederst i koden return str0(self._aar) + str0(self._mnd) + str0(self._dato) def __eq__(self, dato): return dato.aaaammdd() == self.aaaammdd() def __str__(self): datostr = self._ukedag+" "+str(int(self._dato))+". "+ \ maneder[int(self._mnd) - 1]+" "+str(self._aar) return datostr # 3c class Maned: def __init__(self, aar, mn, ud): self._aar = aar self._mndnr = mn # 1 for januar, 2 februar, ... self._navn = maneder[mn-1] self._udag = ud self._datoer = [] def lagManedsKalender(self): # dag er (0 for mandag,...) for den 1. i måneden dagerDenneMnd = dagerIMnd.copy() # hvis man glemmer å ta en kopi vil den globale lista bli endret # og alle februarer etter første skuddår får 29 dager! # Ikke trekk for dette, det er for spesielt if self._aar % 4 == 0: # årstall delelig med 4, skuddår dagerDenneMnd[1] = 29 dag = self._udag for d in range(1, dagerDenneMnd[self._mndnr-1]+1): dato = Dato(str(self._aar), str(self._mndnr), str(d), dag) dag = (dag + 1) % 7 self._datoer.append(dato) return dag # første ukedag i neste måned def hentDatoer(self): # returnerer lista med datoobjekter: return self._datoer def hentDato(self, d): # d er dagnummeret i måneden return self._datoer[d-1] def skriv(self): for dato in self._datoer: print(dato) # 3d class Aar: def __init__(self, å): self._aarstall = å self._jan01 = jan01fallerpå(å) # 0 = mandag, 1 = tirsdag, ... self._maneder = [] # vil inneholde 12 månedsobjekter # self._dager = [] # 365(366) datoobjekter nesteUkedag = self._jan01 for mnd in range(1,13): m = Maned(self._aarstall, mnd, nesteUkedag) nesteUkedag = m.lagManedsKalender() self._maneder.append(m) # løper gjennom månedsobjektene for å lage lista med datoer: def hentMndsListe(self): return self._maneder def hentMnd(self, mndNr): return self._maneder[mndNr-1] def skrivMnd(self, mnd): self._maneder[mnd].skriv() def skriv(self): for mnd in self._maneder: mnd.skriv() # 3e class Kalender: def __init__(self, fra, til): # Kalender fom år fra tom år til self._aar = {} for aar in range(fra, til+1): self._aar[str(aar)] = Aar(aar) def hentAar(self, ar): return self._aar[str(ar)] def hentDato(self, dato): aar = self._aar[dato[0:4]] mnd = int(dato[4:6]) dagnr = int(dato[6:]) dag = aar.hentMnd(mnd).hentDato(dagnr) return dag def hentdatoAlt(self, dato): # alternativ løsning for mnd in aar.hentMndsListe(): for dag in mnd.hentDatoer(): if dag.aaaammdd() == dato: return dag return None # 3g (oppg 3f ny klasse lenger ned) def tellDager(self, dato, inkrement): # løsning som baserer seg på at vi indekserer alle datoer i kalenderen # ved å legge dem kronologisk i ei liste og finner indeksen til # dato (parameter) og legger til (trekker fra hvis negativ) # inkrementet. Tungvindt, men enkelt alleDagerIKalenderen = [] for ar in self._aar: for mnd in range(1,13): for d in self._aar[ar].hentMnd(mnd).hentDatoer(): alleDagerIKalenderen.append(d) indeksTilDato = alleDagerIKalenderen.index(self.hentDato(dato)) return alleDagerIKalenderen[indeksTilDato+inkrement] # 3h def bestemBevegeligeHelligdagerFor(self, år): bvgHelger = { -3:"Skjærtorsdag", # denne kan antas eksisterer -2:"Langfredag", 0:"Første påskedag", 1:"Andre påskedag", 39:"Kristi himmelfartsdag", # 40. påskedag 49:"Første pinsedag", # 50. påskedag 50:"Andre pinsedag" } aar = self._aar[str(år)] paaskedag = fPaaskedag(år).aaaammdd() for inkrement in bvgHelger: self.tellDager(paaskedag, inkrement).settFridag(bvgHelger[inkrement]) def tellDagerAlt(self, dato, inkrement): # alternativ løsning som ikke er optimal i og med at det # ikke tas hensyn til skuddår. Virker også bare framover, dvs. med positivt inkrement # Selv om denne løsningen ikke er optimal, bør slike og lignende løsninger gi full skår dag = int(dato[6:8]) + inkrement mnd = int(dato[4:6]) aar = int(dato[0:4]) print(aar, mnd, dag) while dag - 365 > 0: aar += 1 dag -= 365 print(aar, mnd, dag) while dag - dagerIMnd[mnd-1] > 0: print(dagerIMnd[mnd-1]) print(aar, mnd, dag) dag -= dagerIMnd[mnd-1] mnd += 1 print(aar, mnd, dag) return self._aar[str(aar)].hentMnd(mnd).hentDato(dag) # 3f (faste fridager) class Dato: def __init__(self, å, m, d, dag): self._aar = å self._mnd = m self._dato = d self._dag = dag # 0 for mandag, 1 for tirsdag,... self._ukedag = ukedager[dag] self._fridag = "" if self.aaaammdd()[4:] in fridager: self._fridag = fridager[self.aaaammdd()[4:]] def settFridag(self, tekst): self._fridag = tekst def aaaammdd(self): return str0(self._aar) + str0(self._mnd) + str0(self._dato) def __eq__(self, dato): return dato.aaaammdd() == self.aaaammdd() def __str__(self): datostr = self._ukedag+" "+str(int(self._dato))+". "+ \ maneder[int(self._mnd) - 1]+" "+str(self._aar) if self._fridag != "": datostr = datostr + " (" + self._fridag + ")" return datostr # 3i def testprog(): # Dette er mye, MYE mer kode enn det som trengs # for å gi full uttelling # Tester konstruktør og metoder i Dato: dato = Dato(2021,5,17,0) # mandag 17. mai 2021 print(dato) assert dato.aaaammdd() == "20210517" assert Dato(2021,5,17,0) == Dato(2021,5,17,6) assert Dato(2021,5,17,0) != Dato(1999,5,17,0) print('\n\n') # Maned: mai_21 = Maned(2021, 5, 5) mai_21.lagManedsKalender() assert len(mai_21.hentDatoer()) == 31 print(mai_21.hentDato(17)) mai_21.skriv() print('\n\n') # Aar: år2021 = Aar(2021) assert len(år2021.hentMndsListe()) == 12 år2021.hentMnd(4).skriv() år2021.skrivMnd(5) år2021.skriv() print('\n\n') # Kalender: aar1 = 1901 # int(input("År? ")) aar2 = 2100 # int(input("År? ")) kalender = Kalender(aar1, aar2) dato = kalender.hentDato("19450517") # 17. mai 1945 var en torsdag print(dato) print(kalender.hentAar(1945).hentMnd(5).hentDato(17)) print('\n\n') # 3f (fridager) dato = kalender.hentAar(2021).hentMnd(5).hentDato(23) dato.settFridag("Første pinsedag") print(dato) print('\n\n') # 3g (telle dager fram og tilbake) fpdag2021 = kalender.hentDato("20210404") fpdag2021.settFridag("Første påskedag") print(fpdag2021) skjTorsd = kalender.tellDager(fpdag2021.aaaammdd(), -3) skjTorsd.settFridag("Skjærtorsdag") print(skjTorsd) print('\n\n') # 3h de bevegelige helligdagene kalender.bestemBevegeligeHelligdagerFor(2021) for mnd in [4,5]: # april og mai kalender.hentAar(2021).hentMnd(mnd).skriv() ###################################################################### # Resten er funskjoner og definisjoner som ikke skal kodes, men kunne brukes ###################################################################### def jan01fallerpå(ar): # Gitt årstallet i parameteren år, # returnerer ukedagen 1. januar faller på assert ar > 1700 and ar < 9999 aar = 1901 ukedag = 1 # 1. januar var en tirsdag i 1901 while aar < ar: """ if aar % 4 == 0: skuddar = True if aar % 100 == 0: if aar % 400 == 0: skuddar = True else: skuddar = False else: skuddar = False """ skuddar = (aar % 4 == 0) if aar % 100 == 0: skuddar = False if aar % 400 == 0: skuddar = True if skuddar: # skuddår, og neste 1. januar 2 dager fram ukedag = (ukedag + 2) % 7 else: # ellers 1 dag fram ukedag = (ukedag + 1) % 7 aar = aar + 1 # 0 = mandag, 1 = tirsdag, ..., 6 = søndag return ukedag # Globale lister som gjør overgang mellom navn og tall for måneder # og dager. ukedager = [ "mandag", "tirsdag", "onsdag", "torsdag", "fredag", "lørdag", "søndag" ] maneder = [ "januar", "februar", "mars", "april", "mai", "juni", "juli", "august", "september", "oktober", "november", "desember" ] dagerIMnd = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] def tprint(param): print("Test: "), print(param) def str0(t): if len(str(t)) == 1: return '0'+str(t) else: return str(t) def calcEasterDate(year): """ Use easter date algorithm to calculate the day of easter for a given year. If the year given is in a special range(special_years) then subtract 7 from the final date. Return the date to the user. """ special_years = ['1954', '1981', '2049', '2076'] specyr_sub = 7 a = year % 19 b = year % 4 c = year % 7 d = (19 * a + 24) % 30 e = ((2 * b) + (4 * c) + (6 * d) + 5) % 7 if year in special_years: dateofeaster = (22 + d + e) - specyr_sub else: dateofeaster = 22 + d + e return dateofeaster def fPaaskedag(aar): assert (aar > 1900) and (aar < 2100) pdato = calcEasterDate(aar) if pdato > 31: # paskedag = "April {}".format(pdato - 31) dato = str(pdato - 31) mnd = "4" else: #paskedag = "March {}".format(pdato) dato = str(pdato) mnd = "3" return Dato(str(aar), mnd, dato, 6) fridager = { "0101": "Første nyttårsdag", "0501": "Arbeidernes dag", "0517": "Grunnlovsdag", "1225": "Første juledag", "1226": "Andre juledag" } testprog()