packages feed

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 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` []