V tomto článku naleznete implementaci algoritmu pro zjištění počtu pondělků až pátků v období mezi dvěma zadanými daty.
Realizováno jako uživatelem definovaná funkce v T-SQL pro MS SQL Server 2005 (a asi i nižší).
Algoritmus jsem použil pro tvorbu sestav v jednom systému pro vykazování práce v jedné specifické státní instituci.
Pro zadané období vrací počet pracovních dnů (pondělků-pátků, bez ohledu na svátky v pracovní dny).
Počáteční i koncový den intervalu se také počítá.
Pro nesprávné vstupní údaje (prázdné či překřížené meze) vrací NULL.
POZOR - funkce ke svému chodu využívá ještě funkci ConvertDayOfWeek, kterou popisuji v jiném článku.
Příklady volání:
-- středa 7.11.2007 - úterý 13.11.2007
PRINT dbo.WorkingDays('2007-11-07', '2007-11-13')
-- vrací 5 dnů
Imlementace:
--------------------------------------------------------
-- WorkingDays
--------------------------------------------------------
-- Returns count of working days (mondays-fridays, regardles holidays)
-- within given interval (including starting and ending days of the interval)
-- if the input arguments are invalid (empty or crossed), returns null
--
CREATE FUNCTION dbo.WorkingDays
(
@dt_from datetime, @dt_to datetime
)
RETURNS int
AS
BEGIN
-- check input arguments
IF @dt_from IS NULL OR @dt_to IS NULL
RETURN NULL
IF @dt_from > @dt_to
RETURN NULL
-- === first count number of working days of starting and ending uncomplete weeks ===
DECLARE @starting_week_days int
-- weekdays in starting uncomplete week
-- the algorithm works with week starting on Monday so we have to convert the day of week to it
DECLARE @starting_day int
SET @starting_day = dbo.ConvertDayOfWeek(DatePart(weekday, @dt_from), @@DATEFIRST, 1) -- 1=Monday
SET @starting_week_days = 6 - @starting_day
IF @starting_week_days < 0 SET @starting_week_days = 0
-- weekdays in ending uncomplete week
-- the algorithm works with week starting on Monday so we have to convert the day of week to it
DECLARE @ending_day int
SET @ending_day = dbo.ConvertDayOfWeek(DatePart(weekday, @dt_to), @@DATEFIRST, 1) -- 1=Monday
DECLARE @ending_week_days int
SET @ending_week_days = @ending_day
IF @ending_week_days >= 6 SET @ending_week_days = 5
-- === then count weekdays of middle complete weeks ===
DECLARE @total_days int
DECLARE @total_weekdays int
SET @total_days = datediff(day, @dt_from, @dt_to) + 1
-- the algorithm differs whether the starting and ending week aren't the same
IF (@starting_day <= @ending_day AND @total_days <= 7)
SET @total_weekdays = CASE WHEN @ending_day > 5 THEN 5 ELSE @ending_day END - @starting_day + 1
ELSE -- more than one week
SET @total_weekdays =
@ending_week_days
+ @starting_week_days
-- the result within parenthes is count of days of completw weeks so it is always divisible by 7
+ (@total_days - (7 - @starting_day + 1) - @ending_day) * 5 / 7
-- === return result ===
RETURN @total_weekdays
END
GO