{-|

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.

The example prints all public holidays in Bavaria (Landkreis
Miesbach, Oberbayern) in 2025:

@
import Prelude
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 2025 1 1

end = fromGregorian 2025 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)

main :: IO ()
main = putStrLn $ unlines $ sort $ map unwords holidays
@

@
2025-01-01 Neujahrstag
2025-01-06 Heilige Drei Könige
2025-04-18 Karfreitag
2025-04-21 Ostermontag
2025-05-01 Tag der Arbeit
2025-05-29 Christi Himmelfahrt
2025-06-09 Pfingstmontag
2025-06-19 Fronleichnam
2025-08-15 Mariä Himmelfahrt
2025-10-03 Tag der Deutschen Einheit
2025-11-01 Allerheiligen
2025-12-25 1. Weihnachtsfeiertag
2025-12-26 2. Weihnachtsfeiertag
@

Resources:

Extra holidays are implemented for all 16 federal states. For some
states, we couldn't find official sources; That's why this list
only includes some states.

 - Übersicht: https://de.wikipedia.org/wiki/Gesetzliche_Feiertage_in_Deutschland
 - Weitere Übersicht: https://www.arbeitstage.org/
 - Bayern: https://www.stmi.bayern.de/suv/feiertage/
 - Baden-Württemberg: https://im.baden-wuerttemberg.de/de/service/feiertage
 - Niedersachsen: https://service.niedersachsen.de/portaldeeplink/?tsa_leistung_id=8664664&tsa_sprache=de_DE
 - Hessen: https://innen.hessen.de/buerger-staat/feiertage
 - Rheinland-Pfalz: https://mdi.rlp.de/themen/buerger-und-staat/verfassung-und-verwaltung/sonn-und-feiertagsrecht
 - Brandenburg: https://bravors.brandenburg.de/gesetze/ftg_2003/6
 - Sachsen-Anhalt: https://www.landesrecht.sachsen-anhalt.de/bsst/document/jlr-FeiertGSTrahmen/part/X
 - Thüringen: https://buerger.thueringen.de/detail?pstId=354718
 - Hamburg: https://www.hamburg.de/ferien-und-feiertage/
 - Mecklenburg-Vorpommern u. Berlin (Frauentag): https://www.deutsche-rentenversicherung.de/DRV/DE/Ueber-uns-und-Presse/Presse/Meldungen/2024/240306_frauentag_feiertag_frei.html
 - Saarland: https://www.saarland.de/mibs/DE/themen-aufgaben/aufgaben/buerger_und_staat/sonn_u_feiertagsrecht/feiertagsrecht_node.html
 - Bremen: https://www.transparenz.bremen.de/metainformationen/gesetz-ueber-die-sonn-gedenk-und-feiertage-vom-12-november-1954-145882?asl=bremen203_tpgesetz.c.55340.de&template=20_gp_ifg_meta_detail_d

-}

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 (Int -> FederalState
FederalState -> Int
FederalState -> [FederalState]
FederalState -> FederalState
FederalState -> FederalState -> [FederalState]
FederalState -> FederalState -> FederalState -> [FederalState]
(FederalState -> FederalState)
-> (FederalState -> FederalState)
-> (Int -> FederalState)
-> (FederalState -> Int)
-> (FederalState -> [FederalState])
-> (FederalState -> FederalState -> [FederalState])
-> (FederalState -> FederalState -> [FederalState])
-> (FederalState -> FederalState -> FederalState -> [FederalState])
-> Enum FederalState
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
$csucc :: FederalState -> FederalState
succ :: FederalState -> FederalState
$cpred :: FederalState -> FederalState
pred :: FederalState -> FederalState
$ctoEnum :: Int -> FederalState
toEnum :: Int -> FederalState
$cfromEnum :: FederalState -> Int
fromEnum :: FederalState -> Int
$cenumFrom :: FederalState -> [FederalState]
enumFrom :: FederalState -> [FederalState]
$cenumFromThen :: FederalState -> FederalState -> [FederalState]
enumFromThen :: FederalState -> FederalState -> [FederalState]
$cenumFromTo :: FederalState -> FederalState -> [FederalState]
enumFromTo :: FederalState -> FederalState -> [FederalState]
$cenumFromThenTo :: FederalState -> FederalState -> FederalState -> [FederalState]
enumFromThenTo :: FederalState -> FederalState -> FederalState -> [FederalState]
Enum, FederalState -> FederalState -> Bool
(FederalState -> FederalState -> Bool)
-> (FederalState -> FederalState -> Bool) -> Eq FederalState
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: FederalState -> FederalState -> Bool
== :: FederalState -> FederalState -> Bool
$c/= :: FederalState -> FederalState -> Bool
/= :: FederalState -> FederalState -> Bool
Eq, FederalState
FederalState -> FederalState -> Bounded FederalState
forall a. a -> a -> Bounded a
$cminBound :: FederalState
minBound :: FederalState
$cmaxBound :: FederalState
maxBound :: FederalState
Bounded, Int -> FederalState -> ShowS
[FederalState] -> ShowS
FederalState -> String
(Int -> FederalState -> ShowS)
-> (FederalState -> String)
-> ([FederalState] -> ShowS)
-> Show FederalState
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> FederalState -> ShowS
showsPrec :: Int -> FederalState -> ShowS
$cshow :: FederalState -> String
show :: FederalState -> String
$cshowList :: [FederalState] -> ShowS
showList :: [FederalState] -> ShowS
Show, ReadPrec [FederalState]
ReadPrec FederalState
Int -> ReadS FederalState
ReadS [FederalState]
(Int -> ReadS FederalState)
-> ReadS [FederalState]
-> ReadPrec FederalState
-> ReadPrec [FederalState]
-> Read FederalState
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
$creadsPrec :: Int -> ReadS FederalState
readsPrec :: Int -> ReadS FederalState
$creadList :: ReadS [FederalState]
readList :: ReadS [FederalState]
$creadPrec :: ReadPrec FederalState
readPrec :: ReadPrec FederalState
$creadListPrec :: ReadPrec [FederalState]
readListPrec :: ReadPrec [FederalState]
Read)

-- | Extra federal holidays, no overlap with
-- 'Data.Time.Calendar.BankHoliday.Germany.BankHoliday'.
-- Spezielle Feiertage der Bundesländer.
--
-- \*regional holiday, only applies in parts of the federal state
data ExtraHoliday
  = HeiligeDreiKoenige     -- ^ Heilige Drei Könige (Bayern, Baden-Württemberg, Sachsen-Anhalt)
  | Fronleichnam           -- ^ Fronleichnam (Bayern, Baden-Württemberg, Nordrhein-Westfalen, Hessen, Rheinland-Pfalz, Thüringen*, Saarland)
  | Friedensfest           -- ^ Friedensfest (Bayern*)
  | MariaeHimmelfahrt      -- ^ Mariä Himmelfahrt (Bayern*, Saarland)
  | Allerheiligen          -- ^ Allerheiligen (Bayern, Baden-Württemberg, Nordrhein-Westfalen, Rheinland-Pfalz, Saarland)
  | Reformationstag        -- ^ Reformationstag (Niedersachsen, Sachsen, Schleswig-Holstein, Brandenburg, Sachsen-Anhalt, Thüringen, Hamburg, Mecklenburg-Vorpommern, Bremen)
  | InternationalerFrauentag -- ^ Internationaler Frauentag (Berlin, Mecklenburg-Vorpommern)
  | BussUndBettag          -- ^ Buß- und Bettag (Sachsen)
  deriving (Int -> ExtraHoliday
ExtraHoliday -> Int
ExtraHoliday -> [ExtraHoliday]
ExtraHoliday -> ExtraHoliday
ExtraHoliday -> ExtraHoliday -> [ExtraHoliday]
ExtraHoliday -> ExtraHoliday -> ExtraHoliday -> [ExtraHoliday]
(ExtraHoliday -> ExtraHoliday)
-> (ExtraHoliday -> ExtraHoliday)
-> (Int -> ExtraHoliday)
-> (ExtraHoliday -> Int)
-> (ExtraHoliday -> [ExtraHoliday])
-> (ExtraHoliday -> ExtraHoliday -> [ExtraHoliday])
-> (ExtraHoliday -> ExtraHoliday -> [ExtraHoliday])
-> (ExtraHoliday -> ExtraHoliday -> ExtraHoliday -> [ExtraHoliday])
-> Enum ExtraHoliday
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
$csucc :: ExtraHoliday -> ExtraHoliday
succ :: ExtraHoliday -> ExtraHoliday
$cpred :: ExtraHoliday -> ExtraHoliday
pred :: ExtraHoliday -> ExtraHoliday
$ctoEnum :: Int -> ExtraHoliday
toEnum :: Int -> ExtraHoliday
$cfromEnum :: ExtraHoliday -> Int
fromEnum :: ExtraHoliday -> Int
$cenumFrom :: ExtraHoliday -> [ExtraHoliday]
enumFrom :: ExtraHoliday -> [ExtraHoliday]
$cenumFromThen :: ExtraHoliday -> ExtraHoliday -> [ExtraHoliday]
enumFromThen :: ExtraHoliday -> ExtraHoliday -> [ExtraHoliday]
$cenumFromTo :: ExtraHoliday -> ExtraHoliday -> [ExtraHoliday]
enumFromTo :: ExtraHoliday -> ExtraHoliday -> [ExtraHoliday]
$cenumFromThenTo :: ExtraHoliday -> ExtraHoliday -> ExtraHoliday -> [ExtraHoliday]
enumFromThenTo :: ExtraHoliday -> ExtraHoliday -> ExtraHoliday -> [ExtraHoliday]
Enum, ExtraHoliday -> ExtraHoliday -> Bool
(ExtraHoliday -> ExtraHoliday -> Bool)
-> (ExtraHoliday -> ExtraHoliday -> Bool) -> Eq ExtraHoliday
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: ExtraHoliday -> ExtraHoliday -> Bool
== :: ExtraHoliday -> ExtraHoliday -> Bool
$c/= :: ExtraHoliday -> ExtraHoliday -> Bool
/= :: ExtraHoliday -> ExtraHoliday -> Bool
Eq, ExtraHoliday
ExtraHoliday -> ExtraHoliday -> Bounded ExtraHoliday
forall a. a -> a -> Bounded a
$cminBound :: ExtraHoliday
minBound :: ExtraHoliday
$cmaxBound :: ExtraHoliday
maxBound :: ExtraHoliday
Bounded, Int -> ExtraHoliday -> ShowS
[ExtraHoliday] -> ShowS
ExtraHoliday -> String
(Int -> ExtraHoliday -> ShowS)
-> (ExtraHoliday -> String)
-> ([ExtraHoliday] -> ShowS)
-> Show ExtraHoliday
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> ExtraHoliday -> ShowS
showsPrec :: Int -> ExtraHoliday -> ShowS
$cshow :: ExtraHoliday -> String
show :: ExtraHoliday -> String
$cshowList :: [ExtraHoliday] -> ShowS
showList :: [ExtraHoliday] -> ShowS
Show, ReadPrec [ExtraHoliday]
ReadPrec ExtraHoliday
Int -> ReadS ExtraHoliday
ReadS [ExtraHoliday]
(Int -> ReadS ExtraHoliday)
-> ReadS [ExtraHoliday]
-> ReadPrec ExtraHoliday
-> ReadPrec [ExtraHoliday]
-> Read ExtraHoliday
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
$creadsPrec :: Int -> ReadS ExtraHoliday
readsPrec :: Int -> ReadS ExtraHoliday
$creadList :: ReadS [ExtraHoliday]
readList :: ReadS [ExtraHoliday]
$creadPrec :: ReadPrec ExtraHoliday
readPrec :: ReadPrec ExtraHoliday
$creadListPrec :: ReadPrec [ExtraHoliday]
readListPrec :: ReadPrec [ExtraHoliday]
Read)

-- | Compute the date for a given year and extra holiday.
--
-- >>> toDay 2024 HeiligeDreiKoenige
-- 2024-01-06
toDay :: Year -> ExtraHoliday -> Day
toDay :: Year -> ExtraHoliday -> Day
toDay Year
year ExtraHoliday
HeiligeDreiKoenige      = Year -> Int -> Int -> Day
fromGregorian Year
year Int
1 Int
6
toDay Year
year ExtraHoliday
Fronleichnam            = Year -> Day -> Day
addDays Year
60 (Day -> Day) -> Day -> Day
forall a b. (a -> b) -> a -> b
$ Year -> Day
calculateEasterSunday Year
year
toDay Year
year ExtraHoliday
Friedensfest            = Year -> Int -> Int -> Day
fromGregorian Year
year Int
8 Int
8
toDay Year
year ExtraHoliday
MariaeHimmelfahrt       = Year -> Int -> Int -> Day
fromGregorian Year
year Int
8 Int
15
toDay Year
year ExtraHoliday
Allerheiligen           = Year -> Int -> Int -> Day
fromGregorian Year
year Int
11 Int
1
toDay Year
year ExtraHoliday
InternationalerFrauentag = Year -> Int -> Int -> Day
fromGregorian Year
year Int
3 Int
8
toDay Year
year ExtraHoliday
Reformationstag          = Year -> Int -> Int -> Day
fromGregorian Year
year Int
10 Int
31
toDay Year
year ExtraHoliday
BussUndBettag           = Year -> Day
calculateBussUndBettag Year
year

-- | Compute 'Maybe' the holiday for a given date.
--
-- Note: In some years, two extra holidays may fall on the same
-- day. In such cases this function returns the holiday
-- that is defined first in the 'ExtraHoliday' 'Enum'.
--
-- >>> fromDay (fromGregorian 2024 11 1)
-- Just Allerheiligen
--
-- >>> fromDay (fromGregorian 2024 5 5)
-- Nothing
fromDay :: Day -> Maybe ExtraHoliday
fromDay :: Day -> Maybe ExtraHoliday
fromDay Day
day = [ExtraHoliday] -> Maybe ExtraHoliday
forall a. [a] -> Maybe a
listToMaybe ([ExtraHoliday] -> Maybe ExtraHoliday)
-> [ExtraHoliday] -> Maybe ExtraHoliday
forall a b. (a -> b) -> a -> b
$ (ExtraHoliday -> Bool) -> [ExtraHoliday] -> [ExtraHoliday]
forall a. (a -> Bool) -> [a] -> [a]
filter (\ExtraHoliday
d -> Day
day Day -> Day -> Bool
forall a. Eq a => a -> a -> Bool
== Year -> ExtraHoliday -> Day
toDay (Day -> Year
yearFromDay Day
day) ExtraHoliday
d) [ExtraHoliday
forall a. Bounded a => a
minBound..ExtraHoliday
forall a. Bounded a => a
maxBound]

-- | Compute pairs of date and holiday from start to end (inclusive) 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 :: FederalState -> Day -> Day -> [(Day, ExtraHoliday)]
holidaysBetween FederalState
state Day
start Day
end = ((Day, ExtraHoliday) -> Bool)
-> [(Day, ExtraHoliday)] -> [(Day, ExtraHoliday)]
forall a. (a -> Bool) -> [a] -> [a]
filter (FederalState -> ExtraHoliday -> Bool
isHolidayInState FederalState
state (ExtraHoliday -> Bool)
-> ((Day, ExtraHoliday) -> ExtraHoliday)
-> (Day, ExtraHoliday)
-> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Day, ExtraHoliday) -> ExtraHoliday
forall a b. (a, b) -> b
snd) ([(Day, ExtraHoliday)] -> [(Day, ExtraHoliday)])
-> [(Day, ExtraHoliday)] -> [(Day, ExtraHoliday)]
forall a b. (a -> b) -> a -> b
$ [Maybe (Day, ExtraHoliday)] -> [(Day, ExtraHoliday)]
forall a. [Maybe a] -> [a]
catMaybes ([Maybe (Day, ExtraHoliday)] -> [(Day, ExtraHoliday)])
-> [Maybe (Day, ExtraHoliday)] -> [(Day, ExtraHoliday)]
forall a b. (a -> b) -> a -> b
$ (Day -> Maybe (Day, ExtraHoliday))
-> [Day] -> [Maybe (Day, ExtraHoliday)]
forall a b. (a -> b) -> [a] -> [b]
map (\Day
d -> (Day
d,) (ExtraHoliday -> (Day, ExtraHoliday))
-> Maybe ExtraHoliday -> Maybe (Day, ExtraHoliday)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Day -> Maybe ExtraHoliday
fromDay Day
d) [Day
start..Day
end]

-- | Translate the holiday name to German.
germanHolidayName :: ExtraHoliday -> String
germanHolidayName :: ExtraHoliday -> String
germanHolidayName ExtraHoliday
d = case ExtraHoliday
d of
  ExtraHoliday
HeiligeDreiKoenige     -> String
"Heilige Drei Könige"
  ExtraHoliday
Fronleichnam           -> String
"Fronleichnam"
  ExtraHoliday
Friedensfest           -> String
"Friedensfest"
  ExtraHoliday
MariaeHimmelfahrt      -> String
"Mariä Himmelfahrt"
  ExtraHoliday
Allerheiligen          -> String
"Allerheiligen"
  ExtraHoliday
Reformationstag          -> String
"Reformationstag"
  ExtraHoliday
InternationalerFrauentag -> String
"Internationaler Frauentag"
  ExtraHoliday
BussUndBettag            -> String
"Buß- und Bettag"

-- | Check if 'ExtraHoliday' is a holiday in the given federal state.
--
-- Note: Internationaler Frauentag is a holiday in Berlin (since 2019)
-- and Mecklenburg-Vorpommern (since 2023).
-- However this function doesn't take the year into account and hence
-- is incorrect for earlier years.
--
-- >>> isHolidayInState Bayern Allerheiligen
-- True
--
-- >>> isHolidayInState Berlin Allerheiligen
-- False
isHolidayInState :: FederalState -> ExtraHoliday -> Bool
isHolidayInState :: FederalState -> ExtraHoliday -> Bool
isHolidayInState FederalState
BadenWuerttemberg ExtraHoliday
HeiligeDreiKoenige = Bool
True
isHolidayInState FederalState
BadenWuerttemberg ExtraHoliday
Fronleichnam = Bool
True
isHolidayInState FederalState
BadenWuerttemberg ExtraHoliday
Allerheiligen = Bool
True
isHolidayInState FederalState
Bayern ExtraHoliday
HeiligeDreiKoenige = Bool
True
isHolidayInState FederalState
Bayern ExtraHoliday
Fronleichnam = Bool
True
isHolidayInState FederalState
Bayern ExtraHoliday
Friedensfest = Bool
True
isHolidayInState FederalState
Bayern ExtraHoliday
MariaeHimmelfahrt = Bool
True
isHolidayInState FederalState
Bayern ExtraHoliday
Allerheiligen = Bool
True
isHolidayInState FederalState
Berlin ExtraHoliday
InternationalerFrauentag = Bool
True
isHolidayInState FederalState
NordrheinWestfalen ExtraHoliday
Fronleichnam = Bool
True
isHolidayInState FederalState
NordrheinWestfalen ExtraHoliday
Allerheiligen = Bool
True
isHolidayInState FederalState
Niedersachsen ExtraHoliday
Reformationstag = Bool
True
isHolidayInState FederalState
Hessen ExtraHoliday
Fronleichnam = Bool
True
isHolidayInState FederalState
RheinlandPfalz ExtraHoliday
Allerheiligen = Bool
True
isHolidayInState FederalState
RheinlandPfalz ExtraHoliday
Fronleichnam = Bool
True
isHolidayInState FederalState
Sachsen ExtraHoliday
Reformationstag = Bool
True
isHolidayInState FederalState
Sachsen ExtraHoliday
BussUndBettag = Bool
True
isHolidayInState FederalState
SchleswigHolstein ExtraHoliday
Reformationstag = Bool
True
isHolidayInState FederalState
Brandenburg ExtraHoliday
Reformationstag = Bool
True
isHolidayInState FederalState
SachsenAnhalt ExtraHoliday
HeiligeDreiKoenige = Bool
True
isHolidayInState FederalState
SachsenAnhalt ExtraHoliday
Reformationstag = Bool
True
isHolidayInState FederalState
Thueringen ExtraHoliday
Fronleichnam = Bool
True
isHolidayInState FederalState
Thueringen ExtraHoliday
Reformationstag = Bool
True
isHolidayInState FederalState
Hamburg ExtraHoliday
Reformationstag = Bool
True
isHolidayInState FederalState
MecklenburgVorpommern ExtraHoliday
Reformationstag = Bool
True
isHolidayInState FederalState
MecklenburgVorpommern ExtraHoliday
InternationalerFrauentag = Bool
True
isHolidayInState FederalState
Saarland ExtraHoliday
Fronleichnam = Bool
True
isHolidayInState FederalState
Saarland ExtraHoliday
Allerheiligen = Bool
True
isHolidayInState FederalState
Saarland ExtraHoliday
MariaeHimmelfahrt = Bool
True
isHolidayInState FederalState
Bremen ExtraHoliday
Reformationstag = Bool
True
isHolidayInState FederalState
_ ExtraHoliday
_ = Bool
False

-- | Calculate Buß- und Bettag.
--
-- https://de.wikipedia.org/wiki/Bu%C3%9F-_und_Bettag
calculateBussUndBettag :: Year -> Day
calculateBussUndBettag :: Year -> Day
calculateBussUndBettag Year
year =
   let november23 :: Day
november23 = Year -> Int -> Int -> Day
fromGregorian Year
year Int
11 Int
23
       weekDay :: DayOfWeek
weekDay = Day -> DayOfWeek
dayOfWeek Day
november23
    in if DayOfWeek
weekDay DayOfWeek -> DayOfWeek -> Bool
forall a. Ord a => a -> a -> Bool
<= DayOfWeek
Wednesday
         then Year -> Day -> Day
addDays (Int -> Year
forall a. Integral a => a -> Year
toInteger (Int -> Year) -> Int -> Year
forall a b. (a -> b) -> a -> b
$ DayOfWeek -> Int
forall a. Enum a => a -> Int
fromEnum DayOfWeek
Wednesday Int -> Int -> Int
forall a. Num a => a -> a -> a
- DayOfWeek -> Int
forall a. Enum a => a -> Int
fromEnum DayOfWeek
weekDay Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
7) Day
november23
         else Year -> Day -> Day
addDays (Int -> Year
forall a. Integral a => a -> Year
toInteger (Int -> Year) -> Int -> Year
forall a b. (a -> b) -> a -> b
$ DayOfWeek -> Int
forall a. Enum a => a -> Int
fromEnum DayOfWeek
Wednesday Int -> Int -> Int
forall a. Num a => a -> a -> a
- DayOfWeek -> Int
forall a. Enum a => a -> Int
fromEnum DayOfWeek
weekDay) Day
november23