Technical Article

Count elapsed business days between two dates

,

This is a UDF that counts the days between two dates ignoring weekends and corporate holidays (as supplied in a lookup table). This ignores the time component but could be adjusted should you need to. If both days are on the same work day then the elapsed days is considered 1. If started Monday and completed Tuesday it returns 2. Started Saturday and completed Sunday returns 0. Started Monday and completed the following Monday returns 5. And so on. Holidays are treated the same way as weekends.

This assumes the holiday lookup table is named tblHolidays and the column containing the date (at midnight) is named HolidayDt.

Example Execution yields 9 days less your holidays (8 with Labor day):
select dbo.ElapsedBusinessDays( '9/1/2004', '9/13/2004' )

if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[ElapsedBusinessDays]') and xtype in (N'FN', N'IF', N'TF'))
drop function [dbo].[ElapsedBusinessDays]
GO

SET QUOTED_IDENTIFIER ON 
GO
SET ANSI_NULLS ON 
GO

CREATE FUNCTION [dbo].[ElapsedBusinessDays]
 (@Start smalldatetime, @End smalldatetime)
 RETURNS int
 AS
 BEGIN
 /* Description: Function designed to calculate the number of business days inclusively between two dates. */declare @Days int 
declare @DayIndex smallint
declare @HoldDate smalldatetime

--Make sure the end time is after the begin time
if @End < @Start
     begin
--Backwards. Swap them.
set @HoldDate = @Start
set @Start = @End
set @End = @HoldDate
     end

--Strip the time component off to ease comparisons to the holidays
set @Start = CONVERT(smalldatetime, CONVERT(varchar, @Start, 101 ) )
set @End = CONVERT(smalldatetime, CONVERT(varchar, @End, 101 ) )

set @Days = 0
set @HoldDate = @Start
while @HoldDate <= @End
     begin
--This will convert the current @Start day to a number between 1 and 7 with 1 = Monday and 7 = Sunday no matter what @@DATEFIRST is currently set to.
set @DayIndex = DATEPART( WeekDay, @HoldDate ) - ( 8 - @@DATEFIRST )
if @DayIndex < 1 set @DayIndex = @DayIndex + 7
if @DayIndex <= 5 set @Days = @Days + 1
set @HoldDate = DATEADD( Day, 1, @HoldDate )
     end

set @Days = @Days - ( SELECT COUNT(*)
FROM tblHolidays
WHERE HolidayDt >= @Start
AND HolidayDt <= @End
--This last condition is just to make sure someone didn't put in a holiday on a weekend which could cause negative days.
AND ( ( DATEPART( WeekDay, @HoldDate ) - ( 8 - @@DATEFIRST ) ) + case when (DATEPART( WeekDay, @HoldDate ) - ( 8 - @@DATEFIRST ) ) = 1 then 7 else 0 end ) <= 5 )

RETURN( @Days )
 END 

GO
SET QUOTED_IDENTIFIER OFF 
GO
SET ANSI_NULLS ON 
GO

Rate

You rated this post out of 5. Change rating

Share

Share

Rate

You rated this post out of 5. Change rating