create or replace function easter_sunday(year integer) returns date as $$ DECLARE a integer; b integer; c integer; d integer; e integer; month integer; day integer; easter text; BEGIN a := year % 19; b := year % 4; c := year % 7; d := ((a*19)+24) % 30; e := ((b*2)+(c*4)+(d*6)+5) % 7; IF (d+e < 10) THEN month=3; day=d+e+22; ELSE month=4; day=d+e-9; END IF; easter := year || '-' || month || '-' || day; return easter::date; END; $$ LANGUAGE plpgsql; create or replace function new_year(year integer) returns date as $$ DECLARE day integer; wdate text; BEGIN wdate := year || '-01-01'; select into day extract(DOW from wdate::date); IF (day = 0) THEN return (year || '-01-02')::date; END IF; IF (day = 6) THEN return (year || '-01-03')::date; END IF; return (year || '-01-01')::date; END; $$ LANGUAGE plpgsql; create or replace function christmas(year integer) returns date as $$ DECLARE day integer; wdate text; BEGIN wdate := year || '-12-25'; select into day extract(DOW from wdate::date); IF (day = 0) THEN return (year || '-12-26')::date; END IF; IF (day = 6) THEN return (year || '-12-27')::date; END IF; return (year || '-12-25')::date; END; $$ LANGUAGE plpgsql; create or replace function boxing_day(year integer) returns date as $$ DECLARE day integer; wdate text; BEGIN wdate := year || '-12-25'; select into day extract(DOW from wdate::date); IF (day = 0) THEN return (year || '-12-27')::date; END IF; IF (day > 4) THEN return (year || '-12-28')::date; END IF; return (year || '-12-26')::date; END; $$ LANGUAGE plpgsql; create or replace function may_day(year integer) returns date as $$ DECLARE day integer; wdate text; BEGIN wdate := year || '-05-01'; select into day 9-extract(DOW from wdate::date); IF (day > 7) THEN day := day-7; END IF; return (year || '-05-' || day)::date; END; $$ LANGUAGE plpgsql; create or replace function whitsun(year integer) returns date as $$ DECLARE day integer; wdate text; BEGIN wdate := year || '-05-31'; select into day extract(DOW from wdate::date); IF (day = 0) THEN day := 25; ELSE day := 32-day; END IF; return (year || '-05-' || day)::date; END; $$ LANGUAGE plpgsql; create or replace function summer_bank(year integer) returns date as $$ DECLARE day integer; wdate text; BEGIN wdate := year || '-08-31'; select into day extract(DOW from wdate::date); IF (day = 0) THEN day := 25; ELSE day := 32-day; END IF; return (year || '-08-' || day)::date; END; $$ LANGUAGE plpgsql; create or replace function bank_holidays(year integer) returns setof date as $$ DECLARE wdate date; BEGIN select into wdate new_year(year); return next wdate; select into wdate easter_sunday(year)-'2 days'::interval; return next wdate; select into wdate easter_sunday(year)+'1 days'::interval; return next wdate; select into wdate may_day(year); return next wdate; select into wdate whitsun(year); return next wdate; select into wdate summer_bank(year); return next wdate; select into wdate christmas(year); return next wdate; select into wdate boxing_day(year); return next wdate; return; END; $$ LANGUAGE plpgsql;