I currently have a function in my SQL database that adds a certain amount of business days to a date, e.g. if you enter a date that is a Thursday and add two days, it will r
--Refactoring my original answer... I've added the option to define the starting point of the calculation if the starting date happens to be a weekend day: start from that weekend day or shift to the nearest weekday depending on the direction of the delta.
DECLARE
@input DATE = '2019-06-15', -- if null, then returns null
@delta INT = 1, -- can be positive or negative; null => zero
@startFromWeekend BIT = 1 -- null => zero
-- input is null, delta is zero/null
IF @input IS NULL OR ISNULL(@delta, 0) = 0
SELECT @input
-- input is not null and has delta
ELSE
BEGIN
DECLARE
@input_dw INT = (DATEPART(DW, @input) + @@DATEFIRST - 1) % 7, -- input day of week
@weeks INT = @delta / 5, -- adjust by weeks
@days INT = @delta % 5 -- adjust by days
-- if input is a weekend day, offset it for proper calculation
-- !!important!!: depends on *your* definition of the starting date to perform calculation from
DECLARE @offset INT =
-- start calc from weekend day that is nearest to a weekday depending on delta direction
-- pos delta: effectively Sunday of the weekend (actual: prev Friday)
-- neg delta: effectively Saturday of the weekend (actual: next Monday)
CASE WHEN ISNULL(@startFromWeekend, 0) = 1
THEN CASE WHEN @delta > 0
THEN CASE @input_dw
WHEN 0 THEN -2
WHEN 6 THEN -1
END
ELSE CASE @input_dw
WHEN 0 THEN 1
WHEN 6 THEN 2
END
END
-- start calc from nearest weekday depending on delta direction
-- pos delta: next Monday from the weekend
-- neg delta: prev Friday from the weekend
ELSE CASE WHEN @delta > 0
THEN CASE @input_dw
WHEN 0 THEN 1
WHEN 6 THEN 2
END
ELSE CASE @input_dw
WHEN 0 THEN -2
WHEN 6 THEN -1
END
END
END
-- calculate: add weeks, add days, add initial correction offset
DECLARE @output DATE = DATEADD(DAY, @days + ISNULL(@offset, 0), DATEADD(WEEK, @weeks, @input))
-- finally, if output is weekend, add final correction offset depending on delta direction
SELECT
CASE WHEN (DATEPART(DW, @output) + @@DATEFIRST - 1) % 7 IN (0,6)
THEN CASE
WHEN @delta > 0 THEN DATEADD(DAY, 2, @output)
WHEN @delta < 0 THEN DATEADD(DAY, -2, @output)
END
ELSE @output
END
END