BUSDAYS
Updated 2023-10-06 23:25:11.657000
Syntax
SELECT [westclintech].[wct].[BUSDAYS] (
<@StartDate, datetime,>
,<@EndDate, datetime,>
,<@Holidays, nvarchar(max),>)
Description
Calculate the number of business days from a start date (inclusive) to an end date (exclusive).
Arguments
@Holidays
a comma separated string containing the holiday (non-business) dates to be used in the calculation of the number of business days. You can use the aggregate function NBD NBD to create an appropriately formatted string.
@EndDate
the end date for the calculation. @EndDate is an expression of type datetime or of a type that can be implicitly converted to datetime.
@StartDate
the start date for the calculation. @StartDate is an expression of type datetime or of a type that can be implicitly converted to datetime.
Return Type
int
Remarks
@StartDate cannot be NULL.
@EndDate cannot be NULL.
Saturday and Sunday are always treated as non-business days.
Examples
In this example we will put the holiday string into a variable, using the NBD function and calculate the number of business days and the actual number of days between different date combinations.
/*Populate the variable*/
DECLARE @h as varchar(max);
SET @h =
(
SELECT wct.NBD(d)
FROM
(
SELECT '2010-01-01'
UNION ALL
SELECT '2010-01-18'
UNION ALL
SELECT '2010-02-15'
UNION ALL
SELECT '2010-05-31'
UNION ALL
SELECT '2010-07-05'
UNION ALL
SELECT '2010-09-06'
UNION ALL
SELECT '2010-10-11'
UNION ALL
SELECT '2010-11-25'
UNION ALL
SELECT '2010-12-24'
UNION ALL
SELECT '2010-12-31'
UNION ALL
SELECT '2011-01-17'
UNION ALL
SELECT '2011-02-21'
UNION ALL
SELECT '2011-05-30'
UNION ALL
SELECT '2011-07-04'
UNION ALL
SELECT '2011-09-05'
UNION ALL
SELECT '2011-10-10'
UNION ALL
SELECT '2011-10-11'
UNION ALL
SELECT '2011-11-24'
UNION ALL
SELECT '2011-12-26'
UNION ALL
SELECT '2012-01-02'
UNION ALL
SELECT '2012-01-16'
UNION ALL
SELECT '2012-02-20'
UNION ALL
SELECT '2012-05-28'
UNION ALL
SELECT '2012-07-04'
UNION ALL
SELECT '2012-09-03'
UNION ALL
SELECT '2012-10-08'
UNION ALL
SELECT '2012-11-12'
UNION ALL
SELECT '2012-11-22'
UNION ALL
SELECT '2012-12-25'
UNION ALL
SELECT '2013-01-01'
UNION ALL
SELECT '2013-01-21'
UNION ALL
SELECT '2013-02-18'
UNION ALL
SELECT '2013-05-27'
UNION ALL
SELECT '2013-07-04'
UNION ALL
SELECT '2013-09-02'
UNION ALL
SELECT '2013-10-14'
UNION ALL
SELECT '2013-11-11'
UNION ALL
SELECT '2013-11-28'
UNION ALL
SELECT '2013-12-25'
UNION ALL
SELECT '2014-01-01'
UNION ALL
SELECT '2014-01-20'
UNION ALL
SELECT '2014-02-17'
UNION ALL
SELECT '2014-05-26'
UNION ALL
SELECT '2014-07-04'
UNION ALL
SELECT '2014-09-01'
UNION ALL
SELECT '2014-10-13'
UNION ALL
SELECT '2014-11-11'
UNION ALL
SELECT '2014-11-27'
UNION ALL
SELECT '2014-12-25'
UNION ALL
SELECT '2015-01-01'
UNION ALL
SELECT '2015-01-19'
UNION ALL
SELECT '2015-02-16'
UNION ALL
SELECT '2015-05-25'
UNION ALL
SELECT '2015-07-03'
UNION ALL
SELECT '2015-09-07'
UNION ALL
SELECT '2015-10-12'
UNION ALL
SELECT '2015-11-11'
UNION ALL
SELECT '2015-11-26'
UNION ALL
SELECT '2015-12-25'
) n(d)
);
Calculate business days using the previously declared variable.
SELECT *,
wct.BUSDAYS([Start Date], [End Date], @h) as [Business Days],
DATEDIFF(d, [Start Date], [End Date]) as Actual
FROM
(
SELECT '2015-08-01',
'2014-11-19'
UNION ALL
SELECT '2014-11-01',
'2015-04-12'
UNION ALL
SELECT '2010-03-16',
'2015-12-12'
UNION ALL
SELECT '2009-10-21',
'2011-11-24'
UNION ALL
SELECT '2014-07-22',
'2015-10-13'
UNION ALL
SELECT '2013-02-03',
'2012-02-27'
UNION ALL
SELECT '2013-04-26',
'2015-01-23'
UNION ALL
SELECT '2013-01-07',
'2011-06-07'
UNION ALL
SELECT '2015-08-04',
'2010-09-23'
UNION ALL
SELECT '2013-12-16',
'2015-08-25'
UNION ALL
SELECT '2015-01-02',
'2013-08-07'
UNION ALL
SELECT '2009-12-02',
'2011-10-07'
UNION ALL
SELECT '2014-06-14',
'2015-10-23'
UNION ALL
SELECT '2010-01-15',
'2015-03-13'
UNION ALL
SELECT '2015-01-19',
'2010-06-07'
UNION ALL
SELECT '2014-09-20',
'2012-12-31'
UNION ALL
SELECT '2009-11-08',
'2014-09-01'
UNION ALL
SELECT '2011-07-28',
'2015-09-24'
UNION ALL
SELECT '2010-11-07',
'2011-06-08'
UNION ALL
SELECT '2013-01-08',
'2014-11-26'
UNION ALL
SELECT '2012-07-12',
'2015-02-04'
UNION ALL
SELECT '2012-07-03',
'2012-08-30'
) m([Start Date], [End Date]);
This produces the following result.
{"columns":[{"field":"Start Date","headerClass":"ag-right-aligned-header","cellClass":"ag-right-aligned-cell"},{"field":"End Date","headerClass":"ag-right-aligned-header","cellClass":"ag-right-aligned-cell"},{"field":"Business Days","headerClass":"ag-right-aligned-header","cellClass":"ag-right-aligned-cell"},{"field":"Actual","headerClass":"ag-right-aligned-header","cellClass":"ag-right-aligned-cell"}],"rows":[{"Start Date":"2015-08-01","End Date":"2014-11-19","Business Days":"-176","Actual":"-255"},{"Start Date":"2014-11-01","End Date":"2015-04-12","Business Days":"109","Actual":"162"},{"Start Date":"2010-03-16","End Date":"2015-12-12","Business Days":"1444","Actual":"2097"},{"Start Date":"2009-10-21","End Date":"2011-11-24","Business Days":"529","Actual":"764"},{"Start Date":"2014-07-22","End Date":"2015-10-13","Business Days":"308","Actual":"448"},{"Start Date":"2013-02-03","End Date":"2012-02-27","Business Days":"-236","Actual":"-342"},{"Start Date":"2013-04-26","End Date":"2015-01-23","Business Days":"436","Actual":"637"},{"Start Date":"2013-01-07","End Date":"2011-06-07","Business Days":"-397","Actual":"-580"},{"Start Date":"2015-08-04","End Date":"2010-09-23","Business Days":"-1220","Actual":"-1776"},{"Start Date":"2013-12-16","End Date":"2015-08-25","Business Days":"425","Actual":"617"},{"Start Date":"2015-01-02","End Date":"2013-08-07","Business Days":"-351","Actual":"-513"},{"Start Date":"2009-12-02","End Date":"2011-10-07","Business Days":"467","Actual":"674"},{"Start Date":"2014-06-14","End Date":"2015-10-23","Business Days":"341","Actual":"496"},{"Start Date":"2010-01-15","End Date":"2015-03-13","Business Days":"1294","Actual":"1883"},{"Start Date":"2015-01-19","End Date":"2010-06-07","Business Days":"-1159","Actual":"-1687"},{"Start Date":"2014-09-20","End Date":"2012-12-31","Business Days":"-434","Actual":"-628"},{"Start Date":"2009-11-08","End Date":"2014-09-01","Business Days":"1211","Actual":"1758"},{"Start Date":"2011-07-28","End Date":"2015-09-24","Business Days":"1044","Actual":"1519"},{"Start Date":"2010-11-07","End Date":"2011-06-08","Business Days":"146","Actual":"213"},{"Start Date":"2013-01-08","End Date":"2014-11-26","Business Days":"474","Actual":"687"},{"Start Date":"2012-07-12","End Date":"2015-02-04","Business Days":"642","Actual":"937"},{"Start Date":"2012-07-03","End Date":"2012-08-30","Business Days":"41","Actual":"58"}]}
Let’s assume that we keep holidays on a table indexed by country code in our database. We could run the following SQL using CROSS APPLY to supply holiday information to the function.
SELECT [Start Date]
,[End Date]
,wct.BUSDAYS([Start Date],[End Date],h) as [Business Days]
,DATEDIFF(d,[Start Date],[End Date]) as Actual
FROM (
SELECT '2015-08-01','2014-11-19' UNION ALL
SELECT '2014-11-01','2015-04-12' UNION ALL
SELECT '2010-03-16','2015-12-12' UNION ALL
SELECT '2009-10-21','2011-11-24' UNION ALL
SELECT '2014-07-22','2015-10-13' UNION ALL
SELECT '2013-02-03','2012-02-27' UNION ALL
SELECT '2013-04-26','2015-01-23' UNION ALL
SELECT '2013-01-07','2011-06-07' UNION ALL
SELECT '2015-08-04','2010-09-23' UNION ALL
SELECT '2013-12-16','2015-08-25' UNION ALL
SELECT '2015-01-02','2013-08-07' UNION ALL
SELECT '2009-12-02','2011-10-07' UNION ALL
SELECT '2014-06-14','2015-10-23' UNION ALL
SELECT '2010-01-15','2015-03-13' UNION ALL
SELECT '2015-01-19','2010-06-07' UNION ALL
SELECT '2014-09-20','2012-12-31' UNION ALL
SELECT '2009-11-08','2014-09-01' UNION ALL
SELECT '2011-07-28','2015-09-24' UNION ALL
SELECT '2010-11-07','2011-06-08' UNION ALL
SELECT '2013-01-08','2014-11-26' UNION ALL
SELECT '2012-07-12','2015-02-04' UNION ALL
SELECT '2012-07-03','2012-08-30'
) m([Start Date],[End Date])
CROSS APPLY (
SELECT wct.NBD(Holiday) FROM HOLIDAYS
WHERE Country = 'US'
) k(h)
This produces the following result.
{"columns":[{"field":"Start Date","headerClass":"ag-right-aligned-header","cellClass":"ag-right-aligned-cell"},{"field":"End Date","headerClass":"ag-right-aligned-header","cellClass":"ag-right-aligned-cell"},{"field":"Business Days","headerClass":"ag-right-aligned-header","cellClass":"ag-right-aligned-cell"},{"field":"Actual","headerClass":"ag-right-aligned-header","cellClass":"ag-right-aligned-cell"}],"rows":[{"Start Date":"2015-08-01","End Date":"2014-11-19","Business Days":"-175","Actual":"-255"},{"Start Date":"2014-11-01","End Date":"2015-04-12","Business Days":"108","Actual":"162"},{"Start Date":"2010-03-16","End Date":"2015-12-12","Business Days":"1443","Actual":"2097"},{"Start Date":"2009-10-21","End Date":"2011-11-24","Business Days":"528","Actual":"764"},{"Start Date":"2014-07-22","End Date":"2015-10-13","Business Days":"308","Actual":"448"},{"Start Date":"2013-02-03","End Date":"2012-02-27","Business Days":"-235","Actual":"-342"},{"Start Date":"2013-04-26","End Date":"2015-01-23","Business Days":"436","Actual":"637"},{"Start Date":"2013-01-07","End Date":"2011-06-07","Business Days":"-397","Actual":"-580"},{"Start Date":"2015-08-04","End Date":"2010-09-23","Business Days":"-1220","Actual":"-1776"},{"Start Date":"2013-12-16","End Date":"2015-08-25","Business Days":"425","Actual":"617"},{"Start Date":"2015-01-02","End Date":"2013-08-07","Business Days":"-351","Actual":"-513"},{"Start Date":"2009-12-02","End Date":"2011-10-07","Business Days":"467","Actual":"674"},{"Start Date":"2014-06-14","End Date":"2015-10-23","Business Days":"341","Actual":"496"},{"Start Date":"2010-01-15","End Date":"2015-03-13","Business Days":"1294","Actual":"1883"},{"Start Date":"2015-01-19","End Date":"2010-06-07","Business Days":"-1158","Actual":"-1687"},{"Start Date":"2014-09-20","End Date":"2012-12-31","Business Days":"-433","Actual":"-628"},{"Start Date":"2009-11-08","End Date":"2014-09-01","Business Days":"1210","Actual":"1758"},{"Start Date":"2011-07-28","End Date":"2015-09-24","Business Days":"1044","Actual":"1519"},{"Start Date":"2010-11-07","End Date":"2011-06-08","Business Days":"146","Actual":"213"},{"Start Date":"2013-01-08","End Date":"2014-11-26","Business Days":"474","Actual":"687"},{"Start Date":"2012-07-12","End Date":"2015-02-04","Business Days":"642","Actual":"937"},{"Start Date":"2012-07-03","End Date":"2012-08-30","Business Days":"41","Actual":"58"}]}
Let’s look at what happens if the start date is a Saturday.
DECLARE @sd as datetime;
DECLARE @h as varchar(max);
SET @sd = '2012-05-26';
SET @h =
(
SELECT wct.NBD(holiday)FROM HOLIDAYS WHERE COUNTRY = 'US'
);
SELECT RIGHT(Convert(varchar, @sd, 106), 11) as [Start Date],
RIGHT(Convert(varchar, seriesvalue, 106), 11) as [End Date],
wct.BUSDAYS(@sd, seriesvalue, @h) as [Business Days],
DATEDIFF(d, @sd, seriesvalue) as [Actual Days]
FROM wctMath.wct.SeriesDate(@sd, '2012-06-06', NULL, NULL, NULL);
This produces the following result.
{"columns":[{"field":"Start Date","headerClass":"ag-right-aligned-header","cellClass":"ag-right-aligned-cell"},{"field":"End Date","headerClass":"ag-right-aligned-header","cellClass":"ag-right-aligned-cell"},{"field":"Business Days","headerClass":"ag-right-aligned-header","cellClass":"ag-right-aligned-cell"},{"field":"Actual Days","headerClass":"ag-right-aligned-header","cellClass":"ag-right-aligned-cell"}],"rows":[{"Start Date":"26 May 2012","End Date":"26 May 2012","Business Days":"0","Actual Days":"0"},{"Start Date":"26 May 2012","End Date":"27 May 2012","Business Days":"0","Actual Days":"1"},{"Start Date":"26 May 2012","End Date":"28 May 2012","Business Days":"0","Actual Days":"2"},{"Start Date":"26 May 2012","End Date":"29 May 2012","Business Days":"0","Actual Days":"3"},{"Start Date":"26 May 2012","End Date":"30 May 2012","Business Days":"1","Actual Days":"4"},{"Start Date":"26 May 2012","End Date":"31 May 2012","Business Days":"2","Actual Days":"5"},{"Start Date":"26 May 2012","End Date":"01 Jun 2012","Business Days":"3","Actual Days":"6"},{"Start Date":"26 May 2012","End Date":"02 Jun 2012","Business Days":"3","Actual Days":"7"},{"Start Date":"26 May 2012","End Date":"03 Jun 2012","Business Days":"3","Actual Days":"8"},{"Start Date":"26 May 2012","End Date":"04 Jun 2012","Business Days":"4","Actual Days":"9"},{"Start Date":"26 May 2012","End Date":"05 Jun 2012","Business Days":"5","Actual Days":"10"},{"Start Date":"26 May 2012","End Date":"06 Jun 2012","Business Days":"6","Actual Days":"11"}]}
Notice that is not until 30-May-2012 that one business day has elapsed. There are 4 actual days from 26-May-2012 to 30-May-2012. 26-May-2012 is a Saturday, 27-May-2012 is a Sunday, and 28-May-2012 is holiday. Of the 4 days, 3 are non-business days, so the result is 1 business day.
Let’s look at what happens if the end date is a Sunday.
DECLARE @ed as datetime;
DECLARE @h as varchar(max);
SET @ed = '2012-06-03';
SET @h =
(
SELECT wct.NBD(holiday)FROM HOLIDAYS WHERE COUNTRY = 'US'
);
SELECT RIGHT(Convert(varchar, seriesvalue, 106), 11) as [Start Date],
RIGHT(Convert(varchar, @ed, 106), 11) as [End Date],
wct.BUSDAYS(seriesvalue, @ed, @h) as [Business Days],
DATEDIFF(d, seriesvalue, @ed) as [Actual Days]
FROM wctMath.wct.SeriesDate('2012-05-23', @ed, NULL, NULL, NULL);
This produces the following result.
{"columns":[{"field":"Start Date","headerClass":"ag-right-aligned-header","cellClass":"ag-right-aligned-cell"},{"field":"End Date","headerClass":"ag-right-aligned-header","cellClass":"ag-right-aligned-cell"},{"field":"Business Days","headerClass":"ag-right-aligned-header","cellClass":"ag-right-aligned-cell"},{"field":"Actual Days","headerClass":"ag-right-aligned-header","cellClass":"ag-right-aligned-cell"}],"rows":[{"Start Date":"23 May 2012","End Date":"03 Jun 2012","Business Days":"6","Actual Days":"11"},{"Start Date":"24 May 2012","End Date":"03 Jun 2012","Business Days":"5","Actual Days":"10"},{"Start Date":"25 May 2012","End Date":"03 Jun 2012","Business Days":"4","Actual Days":"9"},{"Start Date":"26 May 2012","End Date":"03 Jun 2012","Business Days":"3","Actual Days":"8"},{"Start Date":"27 May 2012","End Date":"03 Jun 2012","Business Days":"3","Actual Days":"7"},{"Start Date":"28 May 2012","End Date":"03 Jun 2012","Business Days":"3","Actual Days":"6"},{"Start Date":"29 May 2012","End Date":"03 Jun 2012","Business Days":"3","Actual Days":"5"},{"Start Date":"30 May 2012","End Date":"03 Jun 2012","Business Days":"2","Actual Days":"4"},{"Start Date":"31 May 2012","End Date":"03 Jun 2012","Business Days":"1","Actual Days":"3"},{"Start Date":"01 Jun 2012","End Date":"03 Jun 2012","Business Days":"0","Actual Days":"2"},{"Start Date":"02 Jun 2012","End Date":"03 Jun 2012","Business Days":"0","Actual Days":"1"},{"Start Date":"03 Jun 2012","End Date":"03 Jun 2012","Business Days":"0","Actual Days":"0"}]}
Notice that there 11 actual days between 23-May-2012 and 03-Jun-2012, but there are only 6 business days. There are two Saturdays (26-May-2012 and 02-Jun-2012), two Sundays (27-May-2012 and 03-Jun-2012) and one holiday (28-May-2012).
See Also
BUSINESSDATE - Calculate a Business Date from an offset
BUSINESSDATEWE - Calculate a Business Date from an offset and specified weekend days
FIRSTWEEKDAY - Calculate the last occurrence of a weekday in a given month
LASTWEEKDAY - Calculate the first occurrence of a weekday in a given month
NETWORKDAYS - Calculate the number of working days between two dates (inclusive)
YEARFRAC - Calculate the difference between two dates as a fraction of a year