bank-holiday-germany 1.0.0.1 → 1.0.0.2
raw patch · 6 files changed
+247/−26 lines, 6 filesPVP: minor bump suggested
API additions: PVP suggests at least a minor version bump
API changes (from Hackage documentation)
+ Data.Time.Calendar.BankHoliday.Germany: yearFromDay :: Day -> Year
+ Data.Time.Calendar.BankHoliday.Germany.ExtraHolidays: Allerheiligen :: ExtraHoliday
+ Data.Time.Calendar.BankHoliday.Germany.ExtraHolidays: BadenWuerttemberg :: FederalState
+ Data.Time.Calendar.BankHoliday.Germany.ExtraHolidays: Bayern :: FederalState
+ Data.Time.Calendar.BankHoliday.Germany.ExtraHolidays: Berlin :: FederalState
+ Data.Time.Calendar.BankHoliday.Germany.ExtraHolidays: Brandenburg :: FederalState
+ Data.Time.Calendar.BankHoliday.Germany.ExtraHolidays: Bremen :: FederalState
+ Data.Time.Calendar.BankHoliday.Germany.ExtraHolidays: Friedensfest :: ExtraHoliday
+ Data.Time.Calendar.BankHoliday.Germany.ExtraHolidays: Fronleichnam :: ExtraHoliday
+ Data.Time.Calendar.BankHoliday.Germany.ExtraHolidays: Hamburg :: FederalState
+ Data.Time.Calendar.BankHoliday.Germany.ExtraHolidays: HeiligeDreiKoenige :: ExtraHoliday
+ Data.Time.Calendar.BankHoliday.Germany.ExtraHolidays: Hessen :: FederalState
+ Data.Time.Calendar.BankHoliday.Germany.ExtraHolidays: MariaeHimmelfahrt :: ExtraHoliday
+ Data.Time.Calendar.BankHoliday.Germany.ExtraHolidays: MecklenburgVorpommern :: FederalState
+ Data.Time.Calendar.BankHoliday.Germany.ExtraHolidays: Niedersachsen :: FederalState
+ Data.Time.Calendar.BankHoliday.Germany.ExtraHolidays: NordrheinWestfalen :: FederalState
+ Data.Time.Calendar.BankHoliday.Germany.ExtraHolidays: RheinlandPfalz :: FederalState
+ Data.Time.Calendar.BankHoliday.Germany.ExtraHolidays: Saarland :: FederalState
+ Data.Time.Calendar.BankHoliday.Germany.ExtraHolidays: Sachsen :: FederalState
+ Data.Time.Calendar.BankHoliday.Germany.ExtraHolidays: SachsenAnhalt :: FederalState
+ Data.Time.Calendar.BankHoliday.Germany.ExtraHolidays: SchleswigHolstein :: FederalState
+ Data.Time.Calendar.BankHoliday.Germany.ExtraHolidays: Thueringen :: FederalState
+ Data.Time.Calendar.BankHoliday.Germany.ExtraHolidays: data ExtraHoliday
+ Data.Time.Calendar.BankHoliday.Germany.ExtraHolidays: data FederalState
+ Data.Time.Calendar.BankHoliday.Germany.ExtraHolidays: fromDay :: Day -> Maybe ExtraHoliday
+ Data.Time.Calendar.BankHoliday.Germany.ExtraHolidays: germanHolidayName :: ExtraHoliday -> String
+ Data.Time.Calendar.BankHoliday.Germany.ExtraHolidays: holidaysBetween :: FederalState -> Day -> Day -> [(Day, ExtraHoliday)]
+ Data.Time.Calendar.BankHoliday.Germany.ExtraHolidays: instance GHC.Classes.Eq Data.Time.Calendar.BankHoliday.Germany.ExtraHolidays.ExtraHoliday
+ Data.Time.Calendar.BankHoliday.Germany.ExtraHolidays: instance GHC.Classes.Eq Data.Time.Calendar.BankHoliday.Germany.ExtraHolidays.FederalState
+ Data.Time.Calendar.BankHoliday.Germany.ExtraHolidays: instance GHC.Enum.Bounded Data.Time.Calendar.BankHoliday.Germany.ExtraHolidays.ExtraHoliday
+ Data.Time.Calendar.BankHoliday.Germany.ExtraHolidays: instance GHC.Enum.Bounded Data.Time.Calendar.BankHoliday.Germany.ExtraHolidays.FederalState
+ Data.Time.Calendar.BankHoliday.Germany.ExtraHolidays: instance GHC.Enum.Enum Data.Time.Calendar.BankHoliday.Germany.ExtraHolidays.ExtraHoliday
+ Data.Time.Calendar.BankHoliday.Germany.ExtraHolidays: instance GHC.Enum.Enum Data.Time.Calendar.BankHoliday.Germany.ExtraHolidays.FederalState
+ Data.Time.Calendar.BankHoliday.Germany.ExtraHolidays: instance GHC.Read.Read Data.Time.Calendar.BankHoliday.Germany.ExtraHolidays.ExtraHoliday
+ Data.Time.Calendar.BankHoliday.Germany.ExtraHolidays: instance GHC.Read.Read Data.Time.Calendar.BankHoliday.Germany.ExtraHolidays.FederalState
+ Data.Time.Calendar.BankHoliday.Germany.ExtraHolidays: instance GHC.Show.Show Data.Time.Calendar.BankHoliday.Germany.ExtraHolidays.ExtraHoliday
+ Data.Time.Calendar.BankHoliday.Germany.ExtraHolidays: instance GHC.Show.Show Data.Time.Calendar.BankHoliday.Germany.ExtraHolidays.FederalState
+ Data.Time.Calendar.BankHoliday.Germany.ExtraHolidays: isHolidayInState :: FederalState -> ExtraHoliday -> Bool
+ Data.Time.Calendar.BankHoliday.Germany.ExtraHolidays: toDay :: Year -> ExtraHoliday -> Day
Files
- CHANGELOG.md +18/−5
- README.md +35/−5
- bank-holiday-germany.cabal +3/−1
- src/Data/Time/Calendar/BankHoliday/Germany.hs +20/−15
- src/Data/Time/Calendar/BankHoliday/Germany/ExtraHolidays.hs +145/−0
- test/Main.hs +26/−0
CHANGELOG.md view
@@ -1,11 +1,24 @@ # Changelog for `bank-holiday-germany` -All notable changes to this project will be documented in this file.--The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),+The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to the [Haskell Package Versioning Policy](https://pvp.haskell.org/). -## Unreleased+## [1.0.0.0] - 2024-03-14 -## 0.1.0.0 - YYYY-MM-DD+Initial release++## [1.0.0.1] - 2024-03-14++### Added++- Added version bounds of dependencies++## [1.0.0.2] - 2024-03-18++### Added++- Add module `ExtraHolidays` for additional public holidays+- Export `dayToYear` helper function since it is also used by the new module+- Add tests+- Enhance docs
README.md view
@@ -1,15 +1,45 @@ # bank-holiday-germany -This module provides calculation of bank holidays in Germany.+*See below for a German version.* +This package provides calculation of bank holidays and public holidays+in Germany.+ Most of these bank holidays are also public aka legal holidays throughout Germany. You can use `isPublicHoliday` to check if a holiday is also a legal holiday. Legal holidays are generally off for all employees. Bank holidays that-are no legal holidays as well are generally only off for bank employees.+are not legal holidays as well are generally only off for bank employees. -Note: There are even more public holidays in each federal state which-are not covered by this module.+There are even more public holidays in each federal state which+are (partly) covered by the `ExtraHolidays` module of this package. -https://de.wikipedia.org/wiki/Bankfeiertag+See the module documentation for more information.++-----++Dieses Modul behandelt deutsche Bankfeiertage und gesetzliche Feiertage.++Bis auf Heilig Abend und Silvester sind alle Bankfeiertage+gleichzeitig gesetzliche Feiertage in allen Bundesländern der+Bundesrepublik Deutschland. Die Funktion `isPublicHoliday` prüft ob+ein Bankfeiertag auch ein gesetzlicher Feiertag ist.++Gesetzliche Feiertage sind Ländersache – abgesehen vom+[Nationalfeiertag](https://www.bmi.bund.de/DE/themen/verfassung/staatliche-symbole/nationale-feiertage/nationale-feiertage-node.html)+*Tag der deutschen Einheit*.++Bankfeiertage sind in der Regel für Bankangestellte frei.+Gesetzliche Feiertage sind in der Regel für alle Angestellten frei (im+Bundesland für das sie gelten).++Gesetzliche Feiertage der Bundesländer, die nicht gleichzeitig+Bankfeiertage sind, sind im Modul `ExtraHolidays` definiert.++Vorsicht: Manche gesetzliche Feiertage gelten nicht für das ganze+Bundesland sondern nur für bestimmte Landkreise, z.B. das Friedensfest+in Augsburg.++Ein Code-Beispiel im Modul `ExtraHolidays` zeigt, wie alle Feiertage+für ein bestimmtes Bundesland berechnet werden können.
bank-holiday-germany.cabal view
@@ -1,7 +1,7 @@ cabal-version: 3.6 name: bank-holiday-germany-version: 1.0.0.1+version: 1.0.0.2 synopsis: German bank holidays and public holidays description: Calculation of bank holidays and most public holidays in Germany. homepage: https://github.com/schoettl/bank-holiday-germany#readme@@ -18,6 +18,7 @@ library hs-source-dirs: src exposed-modules: Data.Time.Calendar.BankHoliday.Germany+ , Data.Time.Calendar.BankHoliday.Germany.ExtraHolidays build-depends: base >= 4.7 && < 5 , time >= 1.12.2 && < 1.14 default-language: GHC2021@@ -35,6 +36,7 @@ type: exitcode-stdio-1.0 main-is: Main.hs other-modules: Data.Time.Calendar.BankHoliday.Germany+ , Data.Time.Calendar.BankHoliday.Germany.ExtraHolidays hs-source-dirs: test , src build-depends: base
src/Data/Time/Calendar/BankHoliday/Germany.hs view
@@ -8,10 +8,13 @@ holiday is also a legal holiday. Note: There are even more public holidays in each federal state which-are not covered by this module.+are covered by the [@ExtraHolidays@](Data.Time.Calendar.BankHoliday.Germany.ExtraHolidays)+module of this package. -https://de.wikipedia.org/wiki/Bankfeiertag+Resources: + - https://de.wikipedia.org/wiki/Bankfeiertag+ -} module Data.Time.Calendar.BankHoliday.Germany (@@ -22,28 +25,30 @@ holidaysBetween, fromDay, toDay,- germanHolidayName+ germanHolidayName,+ yearFromDay ) where +import Prelude import Data.Time.Calendar import Data.Maybe --- | Data type specifying German bank holidays.+-- | Data type specifying German bank holidays including Christmas Eve and New Year's Eve. -- -- Note: This type cannot be an instance of class 'Ord' because due to -- Easter day calculation the order can change from year to year. data BankHoliday- = NewYearsDay- | GoodFriday -- ^ Karfreitag- | EasterMonday- | LabourDay- | AscensionDay -- ^ Christi Himmelfahrt- | WhitMonday -- ^ Pfingstmontag- | GermanUnityDay- | ChristmasEve- | ChristmasDay- | SecondChristmasDay- | NewYearsEve+ = NewYearsDay -- ^ Neujahrstag+ | GoodFriday -- ^ Karfreitag+ | EasterMonday -- ^ Ostermontag+ | LabourDay -- ^ Tag der Arbeit+ | AscensionDay -- ^ Christi Himmelfahrt+ | WhitMonday -- ^ Pfingstmontag+ | GermanUnityDay -- ^ Tag der Deutschen Einheit+ | ChristmasEve -- ^ Heilig Abend+ | ChristmasDay -- ^ 1. Weihnachtsfeiertag+ | SecondChristmasDay -- ^ 2. Weihnachtsfeiertag+ | NewYearsEve -- ^ Silvestertag deriving (Enum, Eq, Bounded, Show, Read)
+ src/Data/Time/Calendar/BankHoliday/Germany/ExtraHolidays.hs view
@@ -0,0 +1,145 @@++{-|++This module provides additional German public holidays that are not+covered by the [bank holidays](Data.Time.Calendar.BankHoliday.Germany).++Public holidays – except for+'Data.Time.Calendar.BankHoliday.Germany.GermanUnityDay' – are under+federal obligations in Germany („Ländersache“).++Most bank holidays are also federal public holidays+(see 'Data.Time.Calendar.BankHoliday.Germany.isPublicHoliday').+But there are some additional extra holidays which may differ between+federal states.++For example Heilige Drei Könige is not a bank holiday but it is a+public holiday in Bavaria.++Note: The extra holidays are currently only implemented for Bavaria.++Example for computing all public holidays in Bavaria (Landkreis+Miesbach, Oberbayern) in the next couple years:++@+ import Data.List+ import Data.Time+ import qualified Data.Time.Calendar.BankHoliday.Germany as BH+ import qualified Data.Time.Calendar.BankHoliday.Germany.ExtraHolidays as EH++ start = fromGregorian 2024 1 1++ end = fromGregorian 2026 12 31++ holidays :: [[String]]+ holidays = map (\(x,y) -> [show x, BH.germanHolidayName y]) (filter (BH.isPublicHoliday . snd) $ BH.holidaysBetween start end)+ ++ map (\(x,y) -> [show x, EH.germanHolidayName y]) (filter ((/=EH.Friedensfest) . snd) $ EH.holidaysBetween EH.Bayern start end)++ putStrLn $ unlines $ sort $ map unwords holidays+@++Resources:++ - Bayern: https://www.stmi.bayern.de/suv/feiertage/++-}++module Data.Time.Calendar.BankHoliday.Germany.ExtraHolidays (+ ExtraHoliday(..),+ FederalState(..),+ holidaysBetween,+ fromDay,+ toDay,+ germanHolidayName,+ isHolidayInState+) where++import Prelude+import Data.Maybe+import Data.Time.Calendar+import Data.Time.Calendar.BankHoliday.Germany (calculateEasterSunday, yearFromDay)++-- | Germany's federal states – Deutsche Bundesländer.+data FederalState+ = BadenWuerttemberg+ | Bayern+ | Berlin+ | Brandenburg+ | Bremen+ | Hamburg+ | Hessen+ | MecklenburgVorpommern+ | Niedersachsen+ | NordrheinWestfalen+ | RheinlandPfalz+ | Saarland+ | Sachsen+ | SachsenAnhalt+ | SchleswigHolstein+ | Thueringen+ deriving (Enum, Eq, Bounded, Show, Read)++-- | Extra federal holidays, no overlap with+-- 'Data.Time.Calendar.BankHoliday.Germany.BankHoliday'.+-- Spezielle Feiertage der Bundesländer.+--+-- Note: Currently, only Bavaria's extra holidays are implemented.+data ExtraHoliday+ = HeiligeDreiKoenige -- ^ Heilige Drei Könige (Bayern, …)+ | Fronleichnam -- ^ Fronleichnam (Bayern, …)+ | Friedensfest -- ^ Friedensfest (Bayern (Augsburg), …)+ | MariaeHimmelfahrt -- ^ Mariä Himmelfahrt (Bayern (regional), …)+ | Allerheiligen -- ^ Allerheiligen (Bayern, …)+ deriving (Enum, Eq, Bounded, Show, Read)++-- | Compute the date for a given year and extra holiday.+--+-- >>> toDay 2024 HeiligeDreiKoenige+-- 2024-01-06+toDay :: Year -> ExtraHoliday -> Day+toDay year HeiligeDreiKoenige = fromGregorian year 1 6+toDay year Fronleichnam = addDays 60 $ calculateEasterSunday year+toDay year Friedensfest = fromGregorian year 8 8+toDay year MariaeHimmelfahrt = fromGregorian year 8 15+toDay year Allerheiligen = fromGregorian year 11 1++-- | Compute 'Maybe' the holiday for a given date.+--+-- >>> fromDay (fromGregorian 2024 11 1)+-- Just Allerheiligen+--+-- >>> fromDay (fromGregorian 2024 5 5)+-- Nothing+fromDay :: Day -> Maybe ExtraHoliday+fromDay day = listToMaybe $ filter (\d -> day == toDay (yearFromDay day) d) [minBound..maxBound]++-- | Compute pairs of date and holiday from start to end for the given federal state.+--+-- >>> map snd $ holidaysBetween Bayern (fromGregorian 2024 8 8) (fromGregorian 2024 8 15)+-- [Friedensfest,MariaeHimmelfahrt]+holidaysBetween :: FederalState -> Day -> Day -> [(Day, ExtraHoliday)]+holidaysBetween state start end = filter (isHolidayInState state . snd) $ catMaybes $ map (\d -> (d,) <$> fromDay d) [start..end]++-- | Translate the holiday name to German.+germanHolidayName :: ExtraHoliday -> String+germanHolidayName d = case d of+ HeiligeDreiKoenige -> "Heilige Drei Könige"+ Fronleichnam -> "Fronleichnam"+ Friedensfest -> "Friedensfest"+ MariaeHimmelfahrt -> "Mariä Himmelfahrt"+ Allerheiligen -> "Allerheiligen"++-- | Check if 'ExtraHoliday' is a holiday in the given federal state.+--+-- >>> isHolidayInState Bayern Allerheiligen+-- True+--+-- >>> isHolidayInState Berlin Allerheiligen+-- False+isHolidayInState :: FederalState -> ExtraHoliday -> Bool+isHolidayInState Bayern HeiligeDreiKoenige = True+isHolidayInState Bayern Fronleichnam = True+isHolidayInState Bayern Friedensfest = True+isHolidayInState Bayern MariaeHimmelfahrt = True+isHolidayInState Bayern Allerheiligen = True+isHolidayInState _ _ = False
test/Main.hs view
@@ -2,6 +2,7 @@ module Main (main) where import Data.Time.Calendar.BankHoliday.Germany+import Data.Time.Calendar.BankHoliday.Germany.ExtraHolidays qualified as EH import Data.Time.Calendar.WeekDate import Data.Time @@ -21,6 +22,7 @@ main = do doctest ["src/"] hspec $ do+ describe "Data.Time.Calendar.BankHoliday.Germany" $ do describe "holidaysBetween" $ do it "works for Christmas" $ holidaysBetween (day 2024 12 1) (day 2024 12 30)@@ -59,3 +61,27 @@ it "is False only for Chrismas Eve and New Year's Eve" $ length (filter (not . isPublicHoliday) [minBound..maxBound]) `shouldBe` 2+ describe "yearFromDay" $ do+ it "works for any year" $ hedgehog $ do+ y <- forAll $ Gen.integral (Range.linear 0 5000)+ m <- forAll $ Gen.integral (Range.linear 1 12)+ d <- forAll $ Gen.integral (Range.linear 1 28)+ yearFromDay (day y m d) === y++ describe "Data.Time.Calendar.BankHoliday.Germany.ExtraHolidays" $ do+ describe "FederalState" $+ it "has right number of states" $+ length [minBound .. maxBound :: EH.FederalState] `shouldBe` 16+ describe "toDay" $+ it "works for Fronleichnam (depending on Easter Sunday)" $ do+ -- https://www.arbeitstage.org/feiertage/fronleichnam/+ map (\y -> show $ EH.toDay y EH.Fronleichnam) [2024..2027]+ `shouldBe` ["2024-05-30", "2025-06-19", "2026-06-04", "2027-05-27"]+ describe "holidaysBetween" $ do+ it "only has Bavaria's extra holidays" $+ map snd (EH.holidaysBetween EH.Bayern (day 2024 11 1) (day 2024 12 31))+ `shouldBe` [EH.Allerheiligen]+ it "has no holidays for other states yet => otherwise, please add tests" $ do+ let statesExceptBavaria = filter (/=EH.Bayern) [minBound..maxBound]+ let holidays = concatMap (\x -> EH.holidaysBetween x (day 2024 1 1) (day 2024 12 31)) statesExceptBavaria+ holidays `shouldBe` []