Hvor vanskelig er det egentlig å implementere støtte for alle offentlige fridager i Norge? Burde ikke dette vært en naturlig del av dato/kalender-håndteringen i alle landets datasystemer?
La oss starte med å se litt på hvilke dager det er snakk om og hvordan disse kan utledes…
¶Høytidsdager og helligdager i Norge
Det er to offentlige høytidsdager i Norge - 1. mai og 17. mai. Disse er på faste datoer og veldig lett å ta hensyn til.
Også er er det ti helligdager, pluss alle søndager. Av disse ti er tre stykker på faste datoer - 1. januar (nyttårsdag), 25. og 26. desember (1-2. juledag). De andre syv helligdagene settes ut fra påsken (skjærtorsdag, langfredag, 1-2. påskedag, Kristi himmelfartsdag og 1-2. pinsedag).
Så kjapt oppsummert kan man si det slik at den som vet når påsken er lett kan utlede alle offentlige fridager i Norge.
¶Når er egentlig påsken?
Som vi jo alle lærte da vi var små bestemmes påsken slik:
Første påskedag faller på første søndag etter første fullmåne på eller etter vårjevndøgn.
Så.. Betyr dette at vi må ha en månekyndig astronom ansatt for å utlede når påsken er? Neida - allerede i 1816 publiserte Gauss en formel som finner påskedagen - og i 1876 ble det publisert en formel uten unntak for den gregorianske kalenderen vi bruker (se wikipedia).
¶Påskeformelen
Formelen er veldig enkel å bruke og kan se slik ut implementert i Clojure:
(defn easter-sunday
"Compute Easter Sunday given year - using Spencer Jones formula."
[year]
(let [a (mod year 19)
b (quot year 100)
c (mod year 100)
d (quot b 4)
e (mod b 4)
f (quot (+ b 8) 25)
g (quot (+ (- b f) 1) 3)
h (mod (+ (* 19 a) (- b d g) 15) 30)
i (quot c 4)
k (mod c 4)
l (mod (- (+ 32 (* 2 e) (* 2 i)) h k) 7)
m (quot (+ a (* 11 h) (* 22 l)) 451)
n (quot (+ h (- l (* 7 m)) 114) 31)
p (mod (+ h (- l (* 7 m)) 114) 31)]
{:month n :day (+ p 1)}))
Litt crazy variabel-navn her kanskje, men jeg føler at det passer fint å bruke samme navn som i definisjonen. På wikipedia-artikkelen står implementasjonen i JavaScript - om man liker det bedre enn Clojure.
¶Alle fridagene
Gitt formelen som finner påskedagen for et år - kan vi lage et lite program som lister opp alle de norske høytids og helligdagene:
(defn find-set-holidays [year]
#{(date year 1 1)
(date year 5 1)
(date year 5 17)
(date year 12 25)
(date year 12 26)})
(defn find-variable-holidays [year]
(let [esMap (easter-sunday year)
eDay (date year (:month esMap) (:day esMap))]
#{(.minusDays eDay 7)
(.minusDays eDay 3)
(.minusDays eDay 2)
eDay
(.plusDays eDay 1)
(.plusDays eDay 39)
(.plusDays eDay 49)
(.plusDays eDay 50)}))
(defn find-holidays [year]
(union (find-set-holidays year) (find-variable-holidays year)))
Og da er det jo lett å utvide med funksjoner for å sjekke om en gitt dato er helligdag. Eller kanskje legge til 10 arbeidsdager for å finne en betalingsfrist om to uker som ikke er en helligdag eller helg.
¶Biblioteker
Dette er jo veldig lett å implementere selv. Om man skulle ønske å få ferdig kode har jeg laget Clojure-biblioteker for å finne påskedagen og hjelpefunksjoner for datohåndtering:
For mange år siden lagde jeg det samme i Java - tilgjengelig på BEKK sitt nocommons open source bibliotek:
Så enkelt - og veldig nyttig. Regner med alle får dette på plass de neste ukene - så jeg slipper å forholde meg til umulige datoer i nettbanken min :)