This is the best I could do, still use a loop, but use date functions instead of increasing the minutes variable. I hope you will like it.
--set up our source data declare @business_hours table ( work_day varchar(10), open_time varchar(8), close_time varchar(8) ) insert into @business_hours values ('Monday', '08:30:00', '17:00:00') insert into @business_hours values ('Tuesday', '08:30:00', '17:00:00') insert into @business_hours values ('Wednesday', '08:30:00', '17:00:00') insert into @business_hours values ('Thursday', '08:30:00', '17:00:00') insert into @business_hours values ('Friday', '08:30:00', '18:00:00') insert into @business_hours values ('Saturday', '09:00:00', '14:00:00')
declare @holidays table ( holiday varchar(10) ) insert into @holidays values ('2015-01-01') insert into @holidays values ('2015-01-02')
--Im going to assume the SLA of 2 standard business days (0900-1700) = 8*60*2 = 960 declare @start_date datetime = '2014-12-31 16:12:47' declare @time_span int = 960-- time till due in minutes
declare @true bit = 'true' declare @false bit = 'false'
declare @due_date datetime --our output
--other variables declare @date_string varchar(10) declare @today_closing datetime declare @is_workday bit = @true declare @is_holiday bit = @false
--Given our timespan is in minutes, lets also assume we dont care about seconds in start or due dates set @start_date = DATEADD(ss,datepart(ss,@start_date)*-1,@start_date)
while (@time_span > 0) begin
set @due_date = DATEADD(MINUTE,@time_span,@start_date) set @date_string = FORMAT(DATEADD(dd, 0, DATEDIFF(dd, 0, @start_date)),'yyyy-MM-dd') set @today_closing = (select convert(datetime,@date_string + ' ' + close_time) from @business_hours where work_day = DATENAME(weekday,@start_date)) if exists((select work_day from @business_hours where work_day = DATENAME(weekday,@start_date))) set @is_workday = @true else set @is_workday = @false if exists(select holiday from @holidays where holiday = @date_string) set @is_holiday = @true else set @is_holiday = @false if @is_workday = @true and @is_holiday = @false begin if @due_date > @today_closing set @time_span = @time_span - datediff(MINUTE, @start_date, @today_closing) else set @time_span = @time_span - datediff(minute, @start_date, @due_date) end set @date_string = FORMAT(DATEADD(dd, 1, DATEDIFF(dd, 0, @start_date)),'yyyy-MM-dd') set @start_date = CONVERT(datetime, @date_string + ' ' + isnull((select open_time from @business_hours where work_day = DATENAME(weekday,convert(datetime,@date_string))),''))
@due_date
code>