To my surprise, it is actually possible to calculate holidays in SQL, because most of our holidays are at an offset to Easter Sunday.
The example below is based on the Netherlands, but can easily adapted to your locality.
For those of you who want a 7 KB console app to play around with, you can find that on my GitHub: https://github.com/ekelmans/BerekenFeestdagen
And for as long it is up you can also use my Azure Function on: https://isthisdateaholiday.azurewebsites.net/api/fnIsThisDateAHoliday?d=2021-12-25&code=tIsaPavueRYmTkBK7u58IwoAPRc2e9B7AcCcuUVcD0dXCgnCZHQeKA==
/***************************************************************************************
tools.fnCalculateHolidays
****************************************************************************************
Calculates Easter Sunday for a given year, the rest of the holidays can be calculated
as an offset to Easter Sunday using the paschal algorithm
Usage:
select * from tools.fnCalculateHolidays(2025)
****************************************************************************************
Versie : 1.0
Datum : 2021-05-12
Author : Theo Ekelmans
Versie : 1.1
Datum : 2021-05-17
Author : Theo Ekelmans
Change : Goede vrijdag en Bevrijdingsdag geschrapt als vrije dagen.
--------------------------------------------------------------------------------------*/
ALTER FUNCTION [tools].[fnCalculateHolidays]
(
@Y int
)
returns @list table (
[HolidayName] [varchar](50)
, [HolidayDate] datetime
)
AS
begin
declare @jaar varchar(4)
set @jaar = cast(@Y as varchar(4))
-- the paschal algorithm is only valid between 1901 and 2099
if @jaar between 1901 and 2099
begin
-- vaste dagen
declare @nieuwjaar as datetime
declare @bevrijdingsdag as datetime
declare @kerstmis as datetime
declare @tweedekerstdag as datetime
declare @koningsdag as datetime
declare @paasZondag as datetime
declare @paasmaandag as datetime
declare @goedevrijdag as datetime
declare @hemelvaart as datetime
declare @pinksteren as datetime
declare @pinkstermaandag as datetime
set @nieuwjaar = @jaar + '-01-01'
set @bevrijdingsdag = @jaar + '-05-05'
set @kerstmis = @jaar + '-12-25'
set @tweedekerstdag = @jaar + '-12-26'
set @koningsdag = @jaar + '-04-27'
-- Als Koningsdag op zondag valt is het de dag ervoor
if DATENAME(dw, @koningsdag) = 'Sunday'
begin
set @koningsdag = dateadd(day, -1, @koningsdag)
end
-- Reken paasZondag uit
set @paasZondag = (select tools.fnCalculateEasterSunday(@Y));
-- Reken de rest uit via een offset
set @paasmaandag = dateadd(day, 1, @paasZondag); -- 1 dag na pasen
set @goedevrijdag = dateadd(day, -2, @paasZondag); -- 2 dag voor pasen
set @hemelvaart = dateadd(day, 39, @paasZondag); -- 39 dagen na pasen
set @pinksteren = dateadd(day, 49, @paasZondag); -- 10 dagen na hemelvaart
set @pinkstermaandag = dateadd(day, 50, @paasZondag); -- 1 dag na pinksteren
insert into @list ([HolidayName], [HolidayDate])
values ('Nieuwjaar' , @nieuwjaar)
--,('Goede vrijdag' , @goedevrijdag)
,('Pasen' , @paasZondag)
,('Paasmaandag' , @paasmaandag)
,('Koningsdag' , @koningsdag)
--,('Bevrijdingsdag' , @bevrijdingsdag)
,('Hemelvaart' , @hemelvaart)
,('Pinksteren' , @pinksteren)
,('Pinkstermaandag' , @pinkstermaandag)
,('Kerstmis' , @kerstmis)
,('2e Kerstdag' , @tweedekerstdag)
end
return
end