Created
July 3, 2024 19:16
-
-
Save sbailliez/c85778f570ed9b07aeb8307c7d5b8edb to your computer and use it in GitHub Desktop.
Equivalent to WORKDAY function in Excel/Google Sheet (does not support holidays, only handles weekends as saturday/sunday)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
CREATE OR REPLACE FUNCTION f_add_business_day(start_date date, num_days integer) | |
RETURNS date AS | |
$BODY$ | |
SELECT COALESCE( | |
( | |
SELECT workdays.date | |
FROM ( | |
SELECT calendar.date::date, | |
row_number() OVER (ORDER BY CASE WHEN num_days = abs(num_days) THEN calendar.date END, calendar.date DESC) as elapsed_days | |
FROM generate_series( | |
/* start the calendar from day +1 or -1 depending on the sign of num_days */ | |
start_date + (CASE WHEN num_days = abs(num_days) THEN 1 ELSE -1 END), | |
/* until far enough in the future (or past). It is 2*num + 5 days away to cover enough range */ | |
start_date + (((abs(num_days) * 2) + 5) * (CASE WHEN num_days = abs(num_days) THEN 1 ELSE -1 END)), | |
/* increment/decrement by 1 day */ | |
'1 day'::interval * (CASE WHEN num_days = abs(num_days) THEN 1 ELSE -1 END) | |
) calendar(date) | |
/** remove the weekends if there were any holidays we could hardcode them here */ | |
WHERE EXTRACT('dow' FROM calendar.date) NOT IN (0, 6) | |
) workdays | |
/* find the right day N days away */ | |
WHERE elapsed_days = abs(num_days) | |
), | |
/* handle the case when the input is 0, it would not match any row, so return same date */ | |
start_date) | |
$BODY$ | |
LANGUAGE sql IMMUTABLE | |
COST 100; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment