How can I calculate the number of work days between two dates in SQL Server?
Monday to Friday and it must be T-SQL.
This is basically CMS's answer without the reliance on a particular language setting. And since we're shooting for generic, that means it should work for all @@datefirst
settings as well.
datediff(day, , ) + 1 - datediff(week, , ) * 2
/* if start is a Sunday, adjust by -1 */
+ case when datepart(weekday, ) = 8 - @@datefirst then -1 else 0 end
/* if end is a Saturday, adjust by -1 */
+ case when datepart(weekday, ) = (13 - @@datefirst) % 7 + 1 then -1 else 0 end
datediff(week, ...)
always uses a Saturday-to-Sunday boundary for weeks, so that expression is deterministic and doesn't need to be modified (as long as our definition of weekdays is consistently Monday through Friday.) Day numbering does vary according to the @@datefirst
setting and the modified calculations handle this correction with the small complication of some modular arithmetic.
A cleaner way to deal with the Saturday/Sunday thing is to translate the dates prior to extracting a day of week value. After shifting, the values will be back in line with a fixed (and probably more familiar) numbering that starts with 1 on Sunday and ends with 7 on Saturday.
datediff(day, , ) + 1 - datediff(week, , ) * 2
+ case when datepart(weekday, dateadd(day, @@datefirst, )) = 1 then -1 else 0 end
+ case when datepart(weekday, dateadd(day, @@datefirst, )) = 7 then -1 else 0 end
I've tracked this form of the solution back at least as far as 2002 and an Itzik Ben-Gan article. (https://technet.microsoft.com/en-us/library/aa175781(v=sql.80).aspx) Though it needed a small tweak since newer date
types don't allow date arithmetic, it is otherwise identical.
EDIT:
I added back the +1
that had somehow been left off. It's also worth noting that this method always counts the start and end days. It also assumes that the end date is on or after the start date.