holidays (empty) → 0.1.0.0
raw patch · 19 files changed
+890/−0 lines, 19 filesdep +basedep +containersdep +holidays
Dependencies added: base, containers, holidays, tasty, tasty-hunit, tasty-quickcheck, text, time
Files
- CHANGELOG.md +7/−0
- LICENSE +21/−0
- holidays.cabal +63/−0
- src/Holidays.hs +50/−0
- src/Holidays/Base.hs +17/−0
- src/Holidays/DateFinder.hs +174/−0
- src/Holidays/DateTransform.hs +19/−0
- src/Holidays/Germany.hs +153/−0
- src/Holidays/Namibia.hs +29/−0
- src/Holidays/SouthAfrica.hs +28/−0
- src/Holidays/UnitedKingdom.hs +23/−0
- src/Holidays/UnitedStates.hs +26/−0
- tst/Main.hs +20/−0
- tst/Test/Holidays.hs +30/−0
- tst/Test/Holidays/Germany.hs +48/−0
- tst/Test/Holidays/Namibia.hs +52/−0
- tst/Test/Holidays/SouthAfrica.hs +52/−0
- tst/Test/Holidays/UnitedKingdom.hs +43/−0
- tst/Test/Holidays/UnitedStates.hs +35/−0
+ CHANGELOG.md view
@@ -0,0 +1,7 @@+# Revision history for holidays++## **0.1.0.0** - 2025-02-04+- small EDSL for describing holidays+- ZAF, NAM, USA, GBR, DEU+- support for country regions+- unit + property based tests
+ LICENSE view
@@ -0,0 +1,21 @@+MIT License++Copyright (c) 2024 Daniel Cabral++Permission is hereby granted, free of charge, to any person obtaining a copy+of this software and associated documentation files (the "Software"), to deal+in the Software without restriction, including without limitation the rights+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+copies of the Software, and to permit persons to whom the Software is+furnished to do so, subject to the following conditions:++The above copyright notice and this permission notice shall be included in all+copies or substantial portions of the Software.++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE+SOFTWARE.
+ holidays.cabal view
@@ -0,0 +1,63 @@+cabal-version: 3.8++name: holidays+version: 0.1.0.0+synopsis: Library for country public holidays+description:+ Library for country public holidays. Provides a small EDSL to describe holidays for a country.+category: Date+homepage: https://github.com/danielc777888/holidays+license: MIT+license-file: LICENSE+author: Daniel Cabral+maintainer: danielc777888@gmail.com+extra-doc-files: CHANGELOG.md++tested-with: GHC == 9.4.8++source-repository head+ type: git+ location: git://github.com/danielc777888/holidays.git++common common+ ghc-options: -Wall+ build-depends:+ base ^>=4.17.2.1,+ containers ^>=0.7,+ text ^>=2.1,+ time >=1.4 && <2+ default-language: GHC2021++library+ import: common+ exposed-modules:+ Holidays+ other-modules:+ Holidays.Base+ Holidays.DateFinder+ Holidays.DateTransform+ Holidays.Germany+ Holidays.Namibia+ Holidays.SouthAfrica+ Holidays.UnitedKingdom+ Holidays.UnitedStates+ hs-source-dirs: src++test-suite tests+ import: common+ type: exitcode-stdio-1.0+ build-depends:+ holidays,+ tasty >=1.5,+ tasty-hunit >=0.10,+ tasty-quickcheck >=0.10,+ text ^>=2.1+ hs-source-dirs: tst+ main-is: Main.hs+ other-modules:+ Test.Holidays+ Test.Holidays.Germany+ Test.Holidays.Namibia+ Test.Holidays.SouthAfrica+ Test.Holidays.UnitedKingdom+ Test.Holidays.UnitedStates
+ src/Holidays.hs view
@@ -0,0 +1,50 @@+{-# LANGUAGE OverloadedStrings #-}++{- |+This module determines public holidays based on country code and year.+-}+module Holidays (+ ISO_3166_1_Alpha_3,+ Region,+ holidays,+)+where++import Data.Set qualified as S+import Data.Time+import Holidays.Base+import Holidays.DateFinder+import Holidays.DateTransform+import Holidays.Germany qualified as DEU+import Holidays.Namibia qualified as NAM+import Holidays.SouthAfrica qualified as ZAF+import Holidays.UnitedKingdom qualified as GBR+import Holidays.UnitedStates qualified as USA++{- |+Returns a set of public holidays based on the country code (ISO_3166_1_Alpha_3) and a specific year.+If a country is not supported an empty set is returned.+Allowed to specify regions in a country to further determine holidays.++Examples:++@+holidays "DEU" ["BW","BY","BE"] 2025 -- Germany and various states+holidays "USA" [] 2025+@+-}+holidays :: ISO_3166_1_Alpha_3 -> [Region] -> Year -> S.Set Day+holidays countryCode regions year =+ case countryCode of+ "DEU" -> DEU.holidays regions `apply` year+ "GBR" -> GBR.holidays `apply` year+ "NAM" -> NAM.holidays `apply` year+ "USA" -> USA.holidays `apply` year+ "ZAF" -> ZAF.holidays `apply` year+ _ -> S.empty++-- Applies year and transformations to holidays+apply :: (DateFinders, DateTransforms) -> Year -> S.Set Day+apply (finders, transforms) year =+ let validDays = filter valid $ map (\d -> d year) finders -- apply year and filter out invalid days+ in foldr (\d ds -> S.insert (foldr (\t d' -> t ds d') d transforms) ds) S.empty validDays -- apply transforms to valid days
+ src/Holidays/Base.hs view
@@ -0,0 +1,17 @@+module Holidays.Base (+ ISO_3166_1_Alpha_3,+ Region,+ day,+) where++import Data.Text qualified as T+import Data.Time++-- | 3-letter country codes+type ISO_3166_1_Alpha_3 = T.Text++-- | Custom regions for a country+type Region = T.Text++day :: Year -> MonthOfYear -> DayOfMonth -> Day+day = fromGregorian
+ src/Holidays/DateFinder.hs view
@@ -0,0 +1,174 @@+module Holidays.DateFinder (+ after,+ before,+ valid,+ days,+ years,+ sun,+ mon,+ tues,+ wed,+ thurs,+ fri,+ sat,+ jan,+ feb,+ mar,+ apr,+ may,+ jun,+ jul,+ aug,+ sep,+ oct,+ nov,+ dec,+ easterSunday,+ easterMonday,+ goodFriday,+ christmasDay,+ boxingDay,+ newYearsDay,+ ascensionDay,+ workersDay,+ nextOpenDay,+ DateFinders,+) where++import Data.Maybe+import Data.Set qualified as S+import Data.Time++import Data.Time.Calendar.Easter+import Holidays.Base++data Direction = Past | Future++type DateFinders = [Year -> Day]++-- common dates+newYearsDay :: Year -> Day+newYearsDay = jan 1++easterSunday :: Year -> Day+easterSunday = gregorianEaster++easterMonday :: Year -> Day+easterMonday = addDays 1 . easterSunday++goodFriday :: Year -> Day+goodFriday = (1 `fri`) . before . easterSunday++christmasDay :: Year -> Day+christmasDay = dec 25++boxingDay :: Year -> Day+boxingDay = dec 26++ascensionDay :: Year -> Day+ascensionDay = (39 `days`) . after . easterSunday++workersDay :: Year -> Day+workersDay = may 1++-- utils+nullDate :: Day+nullDate = day 0 0 0++valid :: Day -> Bool+valid = not . (nullDate ==)++days :: Integer -> (Integer -> Maybe DayOfWeek -> Day) -> Day+days n f = f n Nothing++years :: (Year -> Bool) -> Day -> Day+years f d = if f (fromIntegral y) then d else nullDate+ where+ (y, _, _) = toGregorian d++-- months+jan :: DayOfMonth -> Year -> Day+jan d y = day y January d++feb :: DayOfMonth -> Year -> Day+feb d y = day y February d++mar :: DayOfMonth -> Year -> Day+mar d y = day y March d++apr :: DayOfMonth -> Year -> Day+apr d y = day y April d++may :: DayOfMonth -> Year -> Day+may d y = day y May d++jun :: DayOfMonth -> Year -> Day+jun d y = day y June d++jul :: DayOfMonth -> Year -> Day+jul d y = day y July d++aug :: DayOfMonth -> Year -> Day+aug d y = day y August d++sep :: DayOfMonth -> Year -> Day+sep d y = day y September d++oct :: DayOfMonth -> Year -> Day+oct d y = day y October d++nov :: DayOfMonth -> Year -> Day+nov d y = day y November d++dec :: DayOfMonth -> Year -> Day+dec d y = day y December d++-- time travel++-- exclusive of before day+before :: Day -> Integer -> Maybe DayOfWeek -> Day+before = timeTravel Past++-- inclusive of after day+after :: Day -> Integer -> Maybe DayOfWeek -> Day+after = timeTravel Future++timeTravel :: Direction -> Day -> Integer -> Maybe DayOfWeek -> Day+timeTravel Past d n w+ | isNothing w = addDays (negate n) d+ | otherwise =+ let diff = fromIntegral $ if dayOfWeek d == fromJust w then 7 else dayOfWeekDiff (dayOfWeek d) (fromJust w)+ in addDays (negate diff - ((n - 1) * 7)) d+timeTravel Future d n w+ | isNothing w = addDays n d+ | otherwise =+ let diff = fromIntegral $ dayOfWeekDiff (fromJust w) (dayOfWeek d)+ in addDays (diff + ((n - 1) * 7)) d++-- week days+sun :: Integer -> (Integer -> Maybe DayOfWeek -> Day) -> Day+sun n f = f n (Just Sunday)++mon :: Integer -> (Integer -> Maybe DayOfWeek -> Day) -> Day+mon n f = f n (Just Monday)++tues :: Integer -> (Integer -> Maybe DayOfWeek -> Day) -> Day+tues n f = f n (Just Tuesday)++wed :: Integer -> (Integer -> Maybe DayOfWeek -> Day) -> Day+wed n f = f n (Just Wednesday)++thurs :: Integer -> (Integer -> Maybe DayOfWeek -> Day) -> Day+thurs n f = f n (Just Thursday)++fri :: Integer -> (Integer -> Maybe DayOfWeek -> Day) -> Day+fri n f = f n (Just Friday)++sat :: Integer -> (Integer -> Maybe DayOfWeek -> Day) -> Day+sat n f = f n (Just Saturday)++nextOpenDay :: [DayOfWeek] -> S.Set Day -> Day -> Day+nextOpenDay ds s d+ | dayOfWeek d `elem` ds = nextOpenDay ds s (addDays 1 d)+ | S.member d s = nextOpenDay ds s (addDays 1 d)+ | otherwise = d
+ src/Holidays/DateTransform.hs view
@@ -0,0 +1,19 @@+module Holidays.DateTransform (+ substituteRule,+ sundayRule,+ DateTransforms+) where++import Data.Set qualified as S+import Data.Time+import Holidays.DateFinder+++type DateTransforms = [S.Set Day -> Day -> Day]++-- general transformations+sundayRule :: S.Set Day -> Day -> Day+sundayRule _ d = if dayOfWeek d == Sunday then addDays 1 d else d -- mon after sunday++substituteRule :: S.Set Day -> Day -> Day+substituteRule = nextOpenDay [Saturday, Sunday]
+ src/Holidays/Germany.hs view
@@ -0,0 +1,153 @@+{--+ references:+ https://en.wikipedia.org/wiki/Public_holidays_in_Germany+ https://publicholidays.de/+--}+{-# LANGUAGE OverloadedStrings #-}++module Holidays.Germany (+ holidays,+) where++import Holidays.Base+import Holidays.DateFinder+import Holidays.DateTransform++holidays :: [Region] -> (DateFinders, DateTransforms)+holidays regions =+ ( concat+ [ federalHolidays,+ regionalHolidays regions+ ],+ []+ )++federalHolidays :: DateFinders+federalHolidays =+ [ newYearsDay,+ goodFriday,+ easterMonday,+ workersDay, -- labour day+ ascensionDay,+ (50 `days`) . after . easterSunday, -- whit monday+ oct 3, -- germany unity day+ christmasDay,+ boxingDay -- second day of christmas+ ]++regionalHolidays :: [Region] -> DateFinders+regionalHolidays =+ concatMap+ ( \r -> case r of+ "BW" -> badenWurttembergHolidays+ "BY" -> bavariaHolidays+ "BE" -> berlinHolidays+ "BB" -> brandenburgHolidays+ "HB" -> bremenHolidays+ "HH" -> hamburgHolidays+ "HE" -> hesseHolidays+ "MV" -> mecklenburgVorpommernHolidays+ "NI" -> lowerSaxonyHolidays+ "NW" -> northRhineWestphaliaHolidays+ "RP" -> rhinelandPalatinateHolidays+ "SL" -> saarlandHolidays+ "SN" -> saxonyHolidays+ "ST" -> saxonyAnhaltHolidays+ "SH" -> schleswigHolsteinHolidays+ "TH" -> thuringiaHolidays+ _ -> []+ )++badenWurttembergHolidays :: DateFinders+badenWurttembergHolidays =+ [ jan 6, -- epiphany+ (60 `days`) . after . easterSunday, -- corpus christi+ nov 1 -- all saints day+ ]++bavariaHolidays :: DateFinders+bavariaHolidays =+ [ jan 6, -- epiphany+ (60 `days`) . after . easterSunday, -- corpus christi+ aug 15, -- assumption day+ nov 1 -- all saints day+ ]++berlinHolidays :: DateFinders+berlinHolidays =+ [ mar 8, -- international womens day+ nov 1, -- all saints day+ years (== 2025) . may 8 -- 80th anniversary of the end of world war 2+ ]++brandenburgHolidays :: DateFinders+brandenburgHolidays =+ [ easterSunday,+ (49 `days`) . after . easterSunday, -- whit sunday+ oct 31 -- reformation day+ ]++bremenHolidays :: DateFinders+bremenHolidays =+ [ oct 31 -- reformation day+ ]++hamburgHolidays :: DateFinders+hamburgHolidays =+ [ oct 31 -- reformation day+ ]++hesseHolidays :: DateFinders+hesseHolidays =+ [ (60 `days`) . after . easterSunday -- corpus christi+ ]++mecklenburgVorpommernHolidays :: DateFinders+mecklenburgVorpommernHolidays =+ [ mar 8, -- international womens day+ oct 31 -- reformation day+ ]++lowerSaxonyHolidays :: DateFinders+lowerSaxonyHolidays =+ [ oct 31 -- reformation day+ ]++northRhineWestphaliaHolidays :: DateFinders+northRhineWestphaliaHolidays =+ [ (60 `days`) . after . easterSunday, -- corpus christi+ nov 1 -- all saints day+ ]++rhinelandPalatinateHolidays :: DateFinders+rhinelandPalatinateHolidays =+ [ (60 `days`) . after . easterSunday, -- corpus christi+ nov 1 -- all saints day+ ]++saarlandHolidays :: DateFinders+saarlandHolidays =+ [ (60 `days`) . after . easterSunday, -- corpus christi+ aug 15, -- assumption day+ nov 1 -- all saints day+ ]++saxonyHolidays :: DateFinders+saxonyHolidays =+ [ (2 `wed`) . before . (4 `sun`) . before . christmasDay -- repentance and prayer day+ ]++saxonyAnhaltHolidays :: DateFinders+saxonyAnhaltHolidays =+ [ jan 6, -- epiphany+ oct 31 -- reformation day+ ]++schleswigHolsteinHolidays :: DateFinders+schleswigHolsteinHolidays =+ []++thuringiaHolidays :: DateFinders+thuringiaHolidays =+ [ sep 20 -- world childrens day+ ]
+ src/Holidays/Namibia.hs view
@@ -0,0 +1,29 @@+-- references:+-- https://en.wikipedia.org/wiki/Public_holidays_in_Namibia++module Holidays.Namibia (+ holidays,+) where++import Holidays.DateFinder+import Holidays.DateTransform++-- Namibia public holidays+holidays :: (DateFinders, DateTransforms)+holidays =+ ( [ newYearsDay,+ mar 21, -- independence day+ goodFriday,+ easterSunday,+ ascensionDay,+ workersDay,+ may 4, -- cassinga day+ may 25, -- africa day+ aug 26, -- heroes day+ dec 10, -- human rights day+ christmasDay,+ boxingDay, -- family day+ years (>= 2025) . may 28 -- genocide remembrance day+ ],+ [sundayRule]+ )
+ src/Holidays/SouthAfrica.hs view
@@ -0,0 +1,28 @@+-- references:+-- https://en.wikipedia.org/wiki/Public_holidays_in_South_Africa++module Holidays.SouthAfrica (+ holidays,+) where++import Holidays.DateFinder+import Holidays.DateTransform++holidays :: (DateFinders, DateTransforms)+holidays =+ ( [ newYearsDay,+ goodFriday,+ easterSunday, -- family day+ mar 21, -- human right day+ apr 27, -- freedom day+ workersDay,+ jun 16, -- youth day+ aug 9, -- womens day+ sep 24, -- heritage day+ dec 16, -- day of reconciliation+ christmasDay,+ boxingDay, -- day of goodwill+ years (== 2024) . may 29 -- general elections 2024+ ],+ [sundayRule]+ )
+ src/Holidays/UnitedKingdom.hs view
@@ -0,0 +1,23 @@+-- references:+-- https://en.wikipedia.org/wiki/Public_holidays_in_the_United_Kingdom++module Holidays.UnitedKingdom (+ holidays,+) where++import Holidays.DateFinder+import Holidays.DateTransform++holidays :: (DateFinders, DateTransforms)+holidays =+ ( [ newYearsDay,+ goodFriday,+ easterSunday,+ (1 `mon`) . after . may 1, -- early may bank holiday+ (1 `mon`) . before . jun 1, -- spring bank holiday+ (1 `mon`) . before . sep 1, -- summer bank holiday+ christmasDay,+ boxingDay+ ],+ [substituteRule]+ )
+ src/Holidays/UnitedStates.hs view
@@ -0,0 +1,26 @@+-- references:+-- https://en.wikipedia.org/wiki/Federal_holidays_in_the_United_States++module Holidays.UnitedStates (+ holidays,+) where++import Holidays.DateFinder+import Holidays.DateTransform++holidays :: (DateFinders, DateTransforms)+holidays =+ ( [ newYearsDay,+ (3 `mon`) . after . jan 1, -- Martin Luther King's birthday+ (3 `mon`) . after . feb 1, -- Georges Washington's birthday+ (1 `mon`) . before . jun 1, -- memorial day, last monday of may+ jun 19, -- juneteenth independence day+ jul 4, -- independence day+ (1 `mon`) . after . sep 1, -- labor day+ (2 `mon`) . after . oct 1, -- columbus day+ nov 11, -- veterans day,+ (4 `thurs`) . after . nov 1, -- thanksgiving day+ christmasDay+ ],+ []+ )
+ tst/Main.hs view
@@ -0,0 +1,20 @@+module Main where++import Test.Holidays.Germany qualified as DEU+import Test.Holidays.Namibia qualified as NAM+import Test.Holidays.SouthAfrica qualified as ZAF+import Test.Holidays.UnitedKingdom qualified as GBR+import Test.Holidays.UnitedStates qualified as USA+import Test.Tasty++main :: IO ()+main = defaultMain tests++tests :: TestTree+tests = testGroup "Holidays tests" [unitTests, propTests]++unitTests :: TestTree+unitTests = testGroup "Unit tests" [DEU.unitTests, GBR.unitTests, NAM.unitTests, USA.unitTests, ZAF.unitTests]++propTests :: TestTree+propTests = testGroup "Holidays property based tests" [DEU.propTests, GBR.propTests, NAM.propTests, USA.propTests, ZAF.propTests]
+ tst/Test/Holidays.hs view
@@ -0,0 +1,30 @@+module Test.Holidays (+ countryPropTests,+ day,+) where++import Data.Set qualified as S+import Data.Time+import Holidays qualified as H+import Test.Tasty+import Test.Tasty.QuickCheck as QC++day :: Year -> MonthOfYear -> DayOfMonth -> Day+day = fromGregorian++countryPropTests :: H.ISO_3166_1_Alpha_3 -> [H.Region] -> TestTree+countryPropTests countryCode regions =+ let uniqueYears c y =+ S.map+ ( \h ->+ let+ (year', _, _) = toGregorian h+ in+ year'+ )+ (H.holidays c regions y)+ in testGroup+ ("Holidays property based tests for country " <> show countryCode)+ [ QC.testProperty "Day always in the same year" $+ \year -> S.singleton year == uniqueYears countryCode year+ ]
+ tst/Test/Holidays/Germany.hs view
@@ -0,0 +1,48 @@+{-# LANGUAGE OverloadedStrings #-}++module Test.Holidays.Germany (+ unitTests,+ propTests,+) where++import Data.Set qualified as S+import Holidays+import Test.Holidays+import Test.Tasty+import Test.Tasty.HUnit++-- german states+regions :: [Region] +regions = ["BW","BY","BE","BB","HB","HH","HE","MV","NI","NW","RP","SL","SN","ST","SH","TH"]++unitTests :: TestTree+unitTests =+ testGroup+ "DEU unit tests"+ [ testCase "2025" $+ S.toAscList (holidays "DEU" regions 2025)+ @?= [ day 2025 1 1,+ day 2025 1 6,+ day 2025 3 8,+ day 2025 4 18,+ day 2025 4 20,+ day 2025 4 21,+ day 2025 5 1,+ day 2025 5 8,+ day 2025 5 29,+ day 2025 6 8,+ day 2025 6 9,+ day 2025 6 19,+ day 2025 8 15,+ day 2025 9 20,+ day 2025 10 3,+ day 2025 10 31,+ day 2025 11 1,+ day 2025 11 19,+ day 2025 12 25,+ day 2025 12 26+ ]+ ]++propTests :: TestTree+propTests = countryPropTests "DEU" regions
+ tst/Test/Holidays/Namibia.hs view
@@ -0,0 +1,52 @@+{-# LANGUAGE OverloadedStrings #-}++module Test.Holidays.Namibia (+ unitTests,+ propTests,+) where++import Data.Set qualified as S+import Holidays+import Test.Holidays+import Test.Tasty+import Test.Tasty.HUnit++unitTests :: TestTree+unitTests =+ testGroup+ "NAM unit tests"+ [ testCase "2024" $+ S.toAscList (holidays "NAM" [] 2024)+ @?= [ day 2024 1 1,+ day 2024 3 21,+ day 2024 3 29,+ day 2024 4 1,+ day 2024 5 1,+ day 2024 5 4,+ day 2024 5 9,+ day 2024 5 25,+ day 2024 8 26,+ day 2024 12 10,+ day 2024 12 25,+ day 2024 12 26+ ],+ testCase "2025" $+ S.toAscList (holidays "NAM" [] 2025)+ @?= [ day 2025 1 1,+ day 2025 3 21,+ day 2025 4 18,+ day 2025 4 21,+ day 2025 5 1,+ day 2025 5 5,+ day 2025 5 26,+ day 2025 5 28,+ day 2025 5 29,+ day 2025 8 26,+ day 2025 12 10,+ day 2025 12 25,+ day 2025 12 26+ ]+ ]++propTests :: TestTree+propTests = countryPropTests "NAM" []
+ tst/Test/Holidays/SouthAfrica.hs view
@@ -0,0 +1,52 @@+{-# LANGUAGE OverloadedStrings #-}++module Test.Holidays.SouthAfrica (+ unitTests,+ propTests,+) where++import Data.Set qualified as S+import Holidays+import Test.Holidays+import Test.Tasty+import Test.Tasty.HUnit++unitTests :: TestTree+unitTests =+ testGroup+ "ZAF unit tests"+ [ testCase "2024" $+ S.toAscList (holidays "ZAF" [] 2024)+ @?= [ day 2024 1 1,+ day 2024 3 21,+ day 2024 3 29,+ day 2024 4 1,+ day 2024 4 27,+ day 2024 5 1,+ day 2024 5 29,+ day 2024 6 17,+ day 2024 8 9,+ day 2024 9 24,+ day 2024 12 16,+ day 2024 12 25,+ day 2024 12 26+ ],+ testCase "2025" $+ S.toAscList (holidays "ZAF" [] 2025)+ @?= [ day 2025 1 1,+ day 2025 3 21,+ day 2025 4 18,+ day 2025 4 21,+ day 2025 4 28,+ day 2025 5 1,+ day 2025 6 16,+ day 2025 8 9,+ day 2025 9 24,+ day 2025 12 16,+ day 2025 12 25,+ day 2025 12 26+ ]+ ]++propTests :: TestTree+propTests = countryPropTests "ZAF" []
+ tst/Test/Holidays/UnitedKingdom.hs view
@@ -0,0 +1,43 @@+{-# LANGUAGE OverloadedStrings #-}++module Test.Holidays.UnitedKingdom (+ unitTests,+ propTests,+) where++import Data.Set qualified as S+import Holidays+import Test.Holidays+import Test.Tasty+import Test.Tasty.HUnit++unitTests :: TestTree+unitTests =+ testGroup+ "GBR unit tests"+ [ testCase "2025" $+ S.toAscList (holidays "GBR" [] 2025)+ @?= [ day 2025 1 1,+ day 2025 4 18,+ day 2025 4 21,+ day 2025 5 5,+ day 2025 5 26,+ day 2025 8 25,+ day 2025 12 25,+ day 2025 12 26+ ],+ testCase "2026" $+ S.toAscList (holidays "GBR" [] 2026)+ @?= [ day 2026 1 1,+ day 2026 4 3,+ day 2026 4 6,+ day 2026 5 4,+ day 2026 5 25,+ day 2026 8 31,+ day 2026 12 25,+ day 2026 12 28+ ]+ ]++propTests :: TestTree+propTests = countryPropTests "GBR" []
+ tst/Test/Holidays/UnitedStates.hs view
@@ -0,0 +1,35 @@+{-# LANGUAGE OverloadedStrings #-}++module Test.Holidays.UnitedStates (+ unitTests,+ propTests,+) where++import Data.Set qualified as S+import Holidays+import Test.Holidays+import Test.Tasty+import Test.Tasty.HUnit++unitTests :: TestTree+unitTests =+ testGroup+ "USA unit tests"+ [ testCase "2025" $+ S.toAscList (holidays "USA" [] 2025)+ @?= [ day 2025 1 1,+ day 2025 1 20,+ day 2025 2 17,+ day 2025 5 26,+ day 2025 6 19,+ day 2025 7 4,+ day 2025 9 1,+ day 2025 10 13,+ day 2025 11 11,+ day 2025 11 27,+ day 2025 12 25+ ]+ ]++propTests :: TestTree+propTests = countryPropTests "USA" []