Recursive CTE to get first business day excluding public holidays

I wanted to write a recursive CTE to calculate the first business day excluding the public holidays for a given year. I have a table with the public holiday for that same year

I like the functions I built to get this done:
create function NthDayOfMonth (@year int, @month smallint, @weekday varchar(15), @nth smallint)
returns datetime
as
begin
declare @the_date datetime, @c_date datetime, @cth smallint
set @cth = 0
set @c_date = convert(varchar,@year)+'-'+convert(varchar,@month)+'-01'
while month(@c_date) = @month
begin
if datename(weekday,@c_date) = @weekday set @cth = @cth + 1
if @cth = @nth and datename(weekday,@c_date) = @weekday set @the_date = @c_date
set @c_date = dateadd(day,1,@c_date)
end
return @the_date
end
GO
create function Holidays(@year int)
returns @table table
date date,
type varchar(10),
name varchar(25)
as
begin
insert into @table
select convert(datetime,convert(varchar,@year)+'-01-01') as date,'Holiday' as type ,'New Years Day' as name UNION ALL
select dbo.NthDayOfMonth(@year,2, 'Monday',3),'Holiday','Family Day' UNION ALL
select dateadd(d,0-case when datepart(weekday,convert(varchar,@year)+'-05-25') in (1,2) then 5+datepart(weekday,convert(varchar,@year)+'-05-25') else datepart(weekday,convert(varchar,@year)+'-05-25')-1 end, convert(varchar,@year)+'-05-25') ,'Holiday','Victoria Day' UNION ALL
select convert(varchar,@year)+'-07-01' ,'Holiday','Canada Day' UNION ALL
select dbo.NthDayOfMonth(@year,8, 'Monday',1),'Holiday','Civic Holiday' UNION ALL
select dbo.NthDayOfMonth(@year,9, 'Monday',1),'Holiday','Labour Day' UNION ALL
select dbo.NthDayofMonth(@year,10,'Monday',2),'Holiday','Thanksgiving' UNION ALL
select convert(varchar,@year)+'-11-11' ,'Holiday','Rememberance Day'UNION ALL
select convert(varchar,@year)+'-12-25' ,'Holiday','Christmas Day' UNION ALL
select convert(varchar,@year)+'-12-26' ,'Holiday','Boxing Day' UNION ALL
SELECT CONVERT(DATE,CONVERT(VARCHAR,@year) + '-0'+CONVERT(VARCHAR, FLOOR((((( (19 * (@year % 19.0)) + FLOOR(@year / 100.0)) - FLOOR((@year / 100.0) / 4) - FLOOR((8 * (@year / 100.0) + 13) / 25.0) + 15) % 30) - (FLOOR((@year % 19.0 + (11 * ((( (19 * (@year % 19.0)) + FLOOR(@year / 100.0)) - FLOOR((@year / 100.0) / 4) - FLOOR((8 * (@year / 100.0) + 13) / 25.0) + 15) % 30))) / 319)) + ((((2 * FLOOR((@year / 100.0)) % 4) + (2*((@year % 100) / 4))) - ((@year % 100) % 4) - ((( (19 * (@year % 19.0)) + FLOOR(@year / 100.0)) - FLOOR((@year / 100.0) / 4) - FLOOR((8 * (@year / 100.0) + 13) / 25.0) + 15) % 30) + (FLOOR((@year % 19.0 + (11 * ((( (19 * (@year % 19.0)) + FLOOR(@year / 100.0)) - FLOOR((@year / 100.0) / 4) - FLOOR((8 * (@year / 100.0) + 13) / 25.0) + 15) % 30))) / 319)) +32) % 7) + 90) / 25))+'-'+CONVERT(VARCHAR,CONVERT(INT,(((( (19 * (@year % 19.0)) + FLOOR(@year / 100.0)) - FLOOR((@year / 100.0) / 4) - FLOOR((8 * (@year / 100.0) + 13) / 25.0) + 15) % 30) - (FLOOR((@year % 19.0 + (11 * ((( (19 * (@year % 19.0)) + FLOOR(@year / 100.0)) - FLOOR((@year / 100.0) / 4) - FLOOR((8 * (@year / 100.0) + 13) / 25.0) + 15) % 30))) / 319)) + ((((2 * FLOOR((@year / 100.0)) % 4) + (2*((@year % 100) / 4))) - ((@year % 100) % 4) - ((( (19 * (@year % 19.0)) + FLOOR(@year / 100.0)) - FLOOR((@year / 100.0) / 4) - FLOOR((8 * (@year / 100.0) + 13) / 25.0) + 15) % 30) + (FLOOR((@year % 19.0 + (11 * ((( (19 * (@year % 19.0)) + FLOOR(@year / 100.0)) - FLOOR((@year / 100.0) / 4) - FLOOR((8 * (@year / 100.0) + 13) / 25.0) + 15) % 30))) / 319)) +32) % 7) + (FLOOR((((( (19 * (@year % 19.0)) + FLOOR(@year / 100.0)) - FLOOR((@year / 100.0) / 4) - FLOOR((8 * (@year / 100.0) + 13) / 25.0) + 15) % 30) - (FLOOR((@year % 19.0 + (11 * ((( (19 * (@year % 19.0)) + FLOOR(@year / 100.0)) - FLOOR((@year / 100.0) / 4) - FLOOR((8 * (@year / 100.0) + 13) / 25.0) + 15) % 30))) / 319)) + ((((2 * FLOOR((@year / 100.0)) % 4) + (2*((@year % 100) / 4))) - ((@year % 100) % 4) - ((( (19 * (@year % 19.0)) + FLOOR(@year / 100.0)) - FLOOR((@year / 100.0) / 4) - FLOOR((8 * (@year / 100.0) + 13) / 25.0) + 15) % 30) + (FLOOR((@year % 19.0 + (11 * ((( (19 * (@year % 19.0)) + FLOOR(@year / 100.0)) - FLOOR((@year / 100.0) / 4) - FLOOR((8 * (@year / 100.0) + 13) / 25.0) + 15) % 30))) / 319)) +32) % 7) + 90) / 25)) + 19) % 32,0))),'Holiday','Easter Sunday' UNION ALL
SELECT DATEADD(DAY,-2,CONVERT(DATE,CONVERT(VARCHAR,@year) + '-0'+CONVERT(VARCHAR, FLOOR((((( (19 * (@year % 19.0)) + FLOOR(@year / 100.0)) - FLOOR((@year / 100.0) / 4) - FLOOR((8 * (@year / 100.0) + 13) / 25.0) + 15) % 30) - (FLOOR((@year % 19.0 + (11 * ((( (19 * (@year % 19.0)) + FLOOR(@year / 100.0)) - FLOOR((@year / 100.0) / 4) - FLOOR((8 * (@year / 100.0) + 13) / 25.0) + 15) % 30))) / 319)) + ((((2 * FLOOR((@year / 100.0)) % 4) + (2*((@year % 100) / 4))) - ((@year % 100) % 4) - ((( (19 * (@year % 19.0)) + FLOOR(@year / 100.0)) - FLOOR((@year / 100.0) / 4) - FLOOR((8 * (@year / 100.0) + 13) / 25.0) + 15) % 30) + (FLOOR((@year % 19.0 + (11 * ((( (19 * (@year % 19.0)) + FLOOR(@year / 100.0)) - FLOOR((@year / 100.0) / 4) - FLOOR((8 * (@year / 100.0) + 13) / 25.0) + 15) % 30))) / 319)) +32) % 7) + 90) / 25))+'-'+CONVERT(VARCHAR,CONVERT(INT,(((( (19 * (@year % 19.0)) + FLOOR(@year / 100.0)) - FLOOR((@year / 100.0) / 4) - FLOOR((8 * (@year / 100.0) + 13) / 25.0) + 15) % 30) - (FLOOR((@year % 19.0 + (11 * ((( (19 * (@year % 19.0)) + FLOOR(@year / 100.0)) - FLOOR((@year / 100.0) / 4) - FLOOR((8 * (@year / 100.0) + 13) / 25.0) + 15) % 30))) / 319)) + ((((2 * FLOOR((@year / 100.0)) % 4) + (2*((@year % 100) / 4))) - ((@year % 100) % 4) - ((( (19 * (@year % 19.0)) + FLOOR(@year / 100.0)) - FLOOR((@year / 100.0) / 4) - FLOOR((8 * (@year / 100.0) + 13) / 25.0) + 15) % 30) + (FLOOR((@year % 19.0 + (11 * ((( (19 * (@year % 19.0)) + FLOOR(@year / 100.0)) - FLOOR((@year / 100.0) / 4) - FLOOR((8 * (@year / 100.0) + 13) / 25.0) + 15) % 30))) / 319)) +32) % 7) + (FLOOR((((( (19 * (@year % 19.0)) + FLOOR(@year / 100.0)) - FLOOR((@year / 100.0) / 4) - FLOOR((8 * (@year / 100.0) + 13) / 25.0) + 15) % 30) - (FLOOR((@year % 19.0 + (11 * ((( (19 * (@year % 19.0)) + FLOOR(@year / 100.0)) - FLOOR((@year / 100.0) / 4) - FLOOR((8 * (@year / 100.0) + 13) / 25.0) + 15) % 30))) / 319)) + ((((2 * FLOOR((@year / 100.0)) % 4) + (2*((@year % 100) / 4))) - ((@year % 100) % 4) - ((( (19 * (@year % 19.0)) + FLOOR(@year / 100.0)) - FLOOR((@year / 100.0) / 4) - FLOOR((8 * (@year / 100.0) + 13) / 25.0) + 15) % 30) + (FLOOR((@year % 19.0 + (11 * ((( (19 * (@year % 19.0)) + FLOOR(@year / 100.0)) - FLOOR((@year / 100.0) / 4) - FLOOR((8 * (@year / 100.0) + 13) / 25.0) + 15) % 30))) / 319)) +32) % 7) + 90) / 25)) + 19) % 32,0)))),'Holiday','Good Friday' UNION ALL
SELECT DATEADD(DAY,1,CONVERT(DATE,CONVERT(VARCHAR,@year) + '-0'+CONVERT(VARCHAR, FLOOR((((( (19 * (@year % 19.0)) + FLOOR(@year / 100.0)) - FLOOR((@year / 100.0) / 4) - FLOOR((8 * (@year / 100.0) + 13) / 25.0) + 15) % 30) - (FLOOR((@year % 19.0 + (11 * ((( (19 * (@year % 19.0)) + FLOOR(@year / 100.0)) - FLOOR((@year / 100.0) / 4) - FLOOR((8 * (@year / 100.0) + 13) / 25.0) + 15) % 30))) / 319)) + ((((2 * FLOOR((@year / 100.0)) % 4) + (2*((@year % 100) / 4))) - ((@year % 100) % 4) - ((( (19 * (@year % 19.0)) + FLOOR(@year / 100.0)) - FLOOR((@year / 100.0) / 4) - FLOOR((8 * (@year / 100.0) + 13) / 25.0) + 15) % 30) + (FLOOR((@year % 19.0 + (11 * ((( (19 * (@year % 19.0)) + FLOOR(@year / 100.0)) - FLOOR((@year / 100.0) / 4) - FLOOR((8 * (@year / 100.0) + 13) / 25.0) + 15) % 30))) / 319)) +32) % 7) + 90) / 25))+'-'+CONVERT(VARCHAR,CONVERT(INT,(((( (19 * (@year % 19.0)) + FLOOR(@year / 100.0)) - FLOOR((@year / 100.0) / 4) - FLOOR((8 * (@year / 100.0) + 13) / 25.0) + 15) % 30) - (FLOOR((@year % 19.0 + (11 * ((( (19 * (@year % 19.0)) + FLOOR(@year / 100.0)) - FLOOR((@year / 100.0) / 4) - FLOOR((8 * (@year / 100.0) + 13) / 25.0) + 15) % 30))) / 319)) + ((((2 * FLOOR((@year / 100.0)) % 4) + (2*((@year % 100) / 4))) - ((@year % 100) % 4) - ((( (19 * (@year % 19.0)) + FLOOR(@year / 100.0)) - FLOOR((@year / 100.0) / 4) - FLOOR((8 * (@year / 100.0) + 13) / 25.0) + 15) % 30) + (FLOOR((@year % 19.0 + (11 * ((( (19 * (@year % 19.0)) + FLOOR(@year / 100.0)) - FLOOR((@year / 100.0) / 4) - FLOOR((8 * (@year / 100.0) + 13) / 25.0) + 15) % 30))) / 319)) +32) % 7) + (FLOOR((((( (19 * (@year % 19.0)) + FLOOR(@year / 100.0)) - FLOOR((@year / 100.0) / 4) - FLOOR((8 * (@year / 100.0) + 13) / 25.0) + 15) % 30) - (FLOOR((@year % 19.0 + (11 * ((( (19 * (@year % 19.0)) + FLOOR(@year / 100.0)) - FLOOR((@year / 100.0) / 4) - FLOOR((8 * (@year / 100.0) + 13) / 25.0) + 15) % 30))) / 319)) + ((((2 * FLOOR((@year / 100.0)) % 4) + (2*((@year % 100) / 4))) - ((@year % 100) % 4) - ((( (19 * (@year % 19.0)) + FLOOR(@year / 100.0)) - FLOOR((@year / 100.0) / 4) - FLOOR((8 * (@year / 100.0) + 13) / 25.0) + 15) % 30) + (FLOOR((@year % 19.0 + (11 * ((( (19 * (@year % 19.0)) + FLOOR(@year / 100.0)) - FLOOR((@year / 100.0) / 4) - FLOOR((8 * (@year / 100.0) + 13) / 25.0) + 15) % 30))) / 319)) +32) % 7) + 90) / 25)) + 19) % 32,0)))),'Holiday','Easter Monday'
update @table
set date =
case when MONTH(date) = 12 AND name != 'Boxing Day' and datepart(weekday,date) = 7 then dateadd(day,2,date)
when MONTH(date) = 12 AND name != 'Boxing Day' and datepart(weekday,date) = 1 then dateadd(day,1,date)
when MONTH(date) = 12 AND name = 'Boxing Day' and datepart(weekday,date) = 7 then dateadd(day,2,date)
when MONTH(date) = 12 AND name = 'Boxing Day' and datepart(weekday,date) = 1 then dateadd(day,2,date)
when MONTH(date) = 12 AND name = 'Boxing Day' and datepart(weekday,date) = 2 then dateadd(day,1,date)
else date
end
return
end
GO
create function Dates(@date datetime)
returns @table table
now datetime,
today datetime,
Month_start datetime,
Month_end datetime,
Prev_Month_Start datetime,
Prev_Month_End datetime,
Week_Start datetime,
Week_End datetime,
Prev_Week_Start datetime,
Prev_Week_End datetime,
Quarter_Start datetime,
Quarter_End datetime,
Prev_Quarter_Start datetime,
Prev_Quarter_End datetime,
Year_Start datetime,
Year_End datetime,
Prev_Year_Start datetime,
Prev_Year_End datetime,
Month_End_TS datetime,
Prev_Month_End_TS datetime,
Week_End_TS datetime,
Prev_Week_End_TS datetime,
Quarter_End_TS datetime,
Prev_Quarter_End_TS datetime,
Year_End_TS datetime,
Prev_Year_End_TS datetime,
Year smallint,
Month smallint,
Day smallint,
Month_Name varchar(15),
Day_Name varchar(15),
WD SMALLINT,
Week INT,
isHoliday bit
as
begin
if @date IS NULL set @date = getdate()
insert into @table
select
@date as now,
convert(datetime,convert(varchar,@date,101)) as today,
dateadd(day,0-day(@date)+1,convert(datetime,convert(varchar,@date,101))) as Month_Start,
dateadd(day,-1,dateadd(month,1,dateadd(day,0-day(@date)+1,convert(datetime,convert(varchar,@date,101))))) as Month_end,
dateadd(month,-1,dateadd(day,0-day(@date)+1,convert(datetime,convert(varchar,@date,101)))) as Prev_Month_start,
dateadd(day,-1-day(@date)+1,convert(datetime,convert(varchar,@date,101))) as Prev_Month_End,
dateadd(day,1-datepart(dw,@date),convert(datetime,convert(varchar,@date,101))) as Week_Start,
dateadd(day,7-datepart(dw,@date),convert(datetime,convert(varchar,@date,101))) as Week_End,
dateadd(day,-6-datepart(dw,@date),convert(datetime,convert(varchar,@date,101))) as Prev_Week_Start,
dateadd(day,0-datepart(dw,@date),convert(datetime,convert(varchar,@date,101))) as Prev_Week_End,
convert(datetime,convert(varchar,year(@date)) +'-'+ right('0'+convert(varchar,((datepart(QUARTER,@date)-1)*3)+1),2)+'-01') as quarter_start,
dateadd(day,-1,dateadd(quarter,1,convert(datetime,convert(varchar,year(@date)) +'-'+ right('0'+convert(varchar,((datepart(QUARTER,@date)-1)*3)+1),2)+'-01'))) as quarter_end,
convert(datetime,convert(varchar,year(dateadd(quarter,-1,@date))) +'-'+ right('0'+convert(varchar,((datepart(QUARTER,dateadd(quarter,-1,@date))-1)*3)+1),2)+'-01') as prev_quarter_start,
dateadd(day,-1,dateadd(quarter,1,convert(datetime,convert(varchar,year(dateadd(quarter,-1,@date))) +'-'+ right('0'+convert(varchar,((datepart(QUARTER,dateadd(quarter,-1,@date))-1)*3)+1),2)+'-01'))) as prev_quarter_end,
dateadd(day,1-day(@date),dateadd(month,1-month(@date),convert(varchar,@date,101))) as Year_Start,
dateadd(year,1,dateadd(day,0-day(@date),dateadd(month,1-month(@date),convert(varchar,@date,101)))) as Year_End,
dateadd(year,-1,dateadd(day,1-day(@date),dateadd(month,1-month(@date),convert(varchar,@date,101)))) as Prev_Year_Start,
dateadd(year,-1,dateadd(year,1,dateadd(day,0-day(@date),dateadd(month,1-month(@date),convert(varchar,@date,101))))) as Prev_Year_End,
dateadd(ms,-3,dateadd(day,0,dateadd(month,1,dateadd(day,0-day(@date)+1,convert(datetime,convert(varchar,@date,101)))))) as Month_End_Ts,
dateadd(ms,-3,dateadd(day,-1-day(@date)+2,convert(datetime,convert(varchar,@date,101)))) as Prev_Month_End_TS,
dateadd(ms,-3,dateadd(day,8-datepart(dw,@date),convert(datetime,convert(varchar,@date,101)))) as Week_End_TS,
dateadd(ms,-3,dateadd(day,1-datepart(dw,@date),convert(datetime,convert(varchar,@date,101)))) as Prev_Week_End_TS,
dateadd(ms,-3,dateadd(day,0,dateadd(quarter,1,convert(datetime,convert(varchar,year(@date)) +'-'+ right('0'+convert(varchar,((datepart(QUARTER,@date)-1)*3)+1),2)+'-01')))) as quarter_end_TS,
dateadd(ms,-3,dateadd(day,0,dateadd(quarter,1,convert(datetime,convert(varchar,year(dateadd(quarter,-1,@date))) +'-'+ right('0'+convert(varchar,((datepart(QUARTER,dateadd(quarter,-1,@date))-1)*3)+1),2)+'-01')))) as prev_quarter_end_TS,
dateadd(ms,-3,dateadd(year,1,dateadd(day,1-day(@date),dateadd(month,1-month(@date),convert(varchar,@date,101))))) as Year_End_TS,
dateadd(ms,-3,dateadd(day,1-day(@date),dateadd(month,1-month(@date),convert(varchar,@date,101)))) as Prev_Year_End_TS,
Year(@date) as Year,
Month(@date) as Month,
Day(@Date) as Day,
datename(month,@Date) as Month_Name,
datename(WEEKDAY,@date) as Day_Name,
datepart(weekday,@date) as WD,
DATEPART(WEEK,@date) AS Week,
COALESCE((SELECT 1
FROM dbo.Holidays(YEAR(@date)) h
WHERE h.date = @date),0) AS isHoliday
return
end
go
The holidays function is set up for Saskatchewan right now, but its a small matter to adjust it to your region.
You can then do this:
DECLARE @calendar TABLE (date DATE)
WHILE (SELECT COUNT(*) FROM @calendar) < 365
BEGIN
INSERT INTO @calendar (date)
VALUES (DATEADD(day,1,(SELECT COALESCE(MAX(date),CURRENT_TIMESTAMP) FROM @calendar)))
END
SELECT MONTH(date) AS month, MIN(date) AS fbd
FROM @calendar c
CROSS APPLY dbo.Dates(c.date)
WHERE DATEPART(DAY,c.date) NOT IN (1,7) AND isHoliday = 0
GROUP BY MONTH(date)

Similar Messages

  • Fucntion to Calculate business days (exclude weekends & holidays) between two days

    Hello,
    I need to be able to calculate business days between two dates excluding weekends and holidays. I do have a date dimension and also flags which denote weekday, holiday. Would really appreciate help in building a udf for the business days calculation.
    Thanks,

    Hi, Please take a look and tweak accordingly. Best of luck.
    --Assuming data dimension table something like the following
    --tblDateDim (DT date primary key,
    flagHoliday bit,
    flagWeekday bit
    CREATE FUNCTION fnBusinessDays (
    @StartDate DATE,
    @EndDate DATE
    RETURNS INT
    AS
    BEGIN
    DECLARE @Days INT ;
    SELECT @Days = count(*)
    FROM tblDateDim --// date dimension
    WHERE
    ( DT BETWEEN @StartDate AND @EndDate) --// dt is date column in the table.
    AND --// also flags which denote weekday, holiday
    flagHoliday = 0 --// flagHoliday= 1--Holiday;= 0 --workingday/businessday
    AND
    flagWeekday = 1 --// FlagWeekday = 1--businessday ; =0 --weekend (Saturday and Sunday)
    RETURN (@Days)
    END
    GO

  • How to: Schedule a job to run on the first business day of the month

    In Oracle 10.2.0.3, is there a way to schedule a repeating job to run on the first business day of the month? For example, if the first of the month falls on a weekend (such as Saturday, 11/01/2008), I would like the job to run automatically on Monday (for example, 11/03/2008) instead.

    set serveroutput on
    begin
      print_dates('FREQ=MONTHLY;BYDAY=MON,TUE,WED,THU,FRI;BYSETPOS=1;',
          to_timestamp_tz('01-JAN-2008 12:00:00','DD-MON-YYYY HH24:MI:SS'), 12);
    end;
    Gives:
    TUE 01-JAN-2008 (001-01) 12:00:00 -07:00 -07:00
    FRI 01-FEB-2008 (032-05) 12:00:00 -07:00 -07:00
    MON 03-MAR-2008 (063-10) 12:00:00 -07:00 -07:00
    TUE 01-APR-2008 (092-14) 12:00:00 -07:00 -07:00
    THU 01-MAY-2008 (122-18) 12:00:00 -07:00 -07:00
    MON 02-JUN-2008 (154-23) 12:00:00 -07:00 -07:00
    TUE 01-JUL-2008 (183-27) 12:00:00 -07:00 -07:00
    FRI 01-AUG-2008 (214-31) 12:00:00 -07:00 -07:00
    MON 01-SEP-2008 (245-36) 12:00:00 -07:00 -07:00
    WED 01-OCT-2008 (275-40) 12:00:00 -07:00 -07:00
    MON 03-NOV-2008 (308-45) 12:00:00 -07:00 -07:00
    MON 01-DEC-2008 (336-49) 12:00:00 -07:00 -07:00
    and the print_dates function is (10.2):
    create or replace procedure print_dates
      cal_string in varchar2,
      start_date in timestamp with time zone,
      nr_of_dates in pls_integer
    is
      date_after timestamp with time zone := start_date - interval '1' second;
      next_execution_date timestamp with time zone;
    begin
      dbms_output.put_line('  -->');
      for i in 1 .. nr_of_dates
      loop
        dbms_scheduler.evaluate_calendar_string
         (cal_string, start_date, date_after, next_execution_date);
        dbms_output.put_line(to_char(next_execution_date,
                        'DY DD-MON-YYYY (DDD-IW) HH24:MI:SS TZD TZH TZR'));
        date_after := next_execution_date;
      end loop;
    end;
    [\pre]                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               

  • Number of business days (excluding holidays) ?

    Hi All,
    What is the SQL query to find number of business days (excluding holidays) between 2 given dates ?
    List of Holidays will be maintained as a separate table.
    I need a SQL query rather than a stored procedure or function.
    I am using oracle 9i.
    Thanks in advance.

    Does this thread help?
    Need to find number of business days - query pls

  • Task Scheduler exclude public holidays

    I have a script that has to be run every workday. At the moment I have set it to run from Monday to Friday once a day but I need it to run once a day from Monday to Friday excluding public holidays like Xmas, Easter, etc.
    I could accomplish this by creating multiple schedules between public holidays and by doing this  I would exclude the public holidays. 
    What would be the best practice for accomplishing this?

    I am not aware about a way to achieve that. You might want to think about using Microsoft System Center Orchestrator which allows implementing more advanced scheduled tasks.
    This posting is provided AS IS with no warranties or guarantees , and confers no rights.
    Ahmed MALEK
    My Website Link
    My Linkedin Profile
    My MVP Profile

  • Get Next business day conditionally

    Hi All,
    I have a calendar table with all federal holidays, saturdays and sundays flagged to 1.
    I need help in finding the next business day from givendate and that too Conditionallly.. means
    Lets say today's date is 01/02/2014(wednesday) and I want to know the next businessday after 10 days which would be 01/16/2014(thursday). Exclude saturdays and sundays in between.
    I started like this..but gives me wrong date..
    Also, when 10th day is saturday or sunday or any holiday it should give next business day.
    so i need help in tweaking my query.
    select NextBusinessDay = min(a.Date)+10
    from  [dbo].[Calendar] a
    where
     a.Date > GETDATE() 
     and a.day_Name not in ('Saturday','Sunday')
     and a.IsHoliday <> 1
    Thanks,
    RH
    sql

    Try this out:
    DECLARE @calendar TABLE (date DATE, holiday BIT, weekend BIT)
    DECLARE @i INT = 0
    SET NOCOUNT ON
    WHILE @i < 50
    BEGIN
    INSERT INTO @calendar (date, holiday, weekend)
    VALUES (DATEADD(DAY,@i,'2014-01-01'),0,CASE WHEN DATEPART(WEEKDAY,DATEADD(DAY,@i,'2014-01-01')) IN (1,7) THEN 1 ELSE 0 END)
    SET @i = @i + 1
    END
    UPDATE @calendar SET holiday = 1 WHERE date = '2014-01-20'
    SET NOCOUNT OFF
    SELECT max(date)
    FROM (
    SELECT TOP 10 *
    FROM @calendar
    WHERE date > '2014-01-02'
    AND holiday <> 1
    AND weekend <> 1
    ) a
    Obviously I've simulated your calendar, and forced a date into it.

  • Need Help Calculating Business Days AND omitting Holidays...

    Post Author: dkotenoglou
    CA Forum: Formula
    Thanks to the people here I was able to get a nice formula to help me calculate the amount of business days between two days.//Crystal syntax
    Local DateTimeVar d1 := ;
    Local DateTimeVar d2 := ;
    DateDiff ("d", d1, d2) -
         DateDiff ("ww", d1, d2, crSaturday) - 
         DateDiff ("ww", d1, d2, crSunday) This works great.  I wanted to add the ability to omit US Holidays.  Now this is a straight Crystal Reports install without an SQL backend so I cannot use any formulas there.Is there a parameter? I can use to manually create a table of dates to omit?  The only reason I ask is that our company was closed during the holidays so my day reports are really high. I do not mind typing a long list of days manually (12/24/2007, 12/25/2007, etc) but I need to know how to best integrate that list into the formula.  

    Post Author: V361
    CA Forum: Formula
    If you have CR XI, there is another example as well, in the sample reports,  look at feature examples, custom functions.rpt   this code is from that example.
    Function cdDateAddSkipHolidays (nWorkingDays As Number, startDateTime As DateTime) As DateTime    'the result = startDateTime + nWorkingDays + nHolidays (including weekends)    'the algorithm below also works when nWorkingDays is negative
        Dim totalDays    'give a rough estimate for total days. For each 5 work days there are 7    'days. Also add in an extra 2 weekend days to account for a partial week.    totalDays = Fix(nWorkingDays * 7 / 5 + 1) + 2
        Dim iteratedDiff    iteratedDiff = cdDateDiffSkipHolidays (startDateTime, startDateTime + totalDays)
        If (iteratedDiff >= nWorkingDays) Then        Do While iteratedDiff >= nWorkingDays            totalDays = totalDays - 1            iteratedDiff = cdDateDiffSkipHolidays (startDateTime, startDateTime + totalDays)        Loop        cdDateAddSkipHolidays = startDateTime + totalDays + 1    Else        Do While iteratedDiff < nWorkingDays            totalDays = totalDays + 1            iteratedDiff = cdDateDiffSkipHolidays (startDateTime, startDateTime + totalDays)        Loop         cdDateAddSkipHolidays = startDateTime + totalDays    End If
    End Function

  • How to calculate days between 2 dates excluding public holidays over SAP ?

    Hi
    Have a universe over SAP data. Trying to calculate days between 2 dates. SAP holds Public Holiday data in various tables e.g  Thol and data is updated via scal. Using my univeres as a source I want to run  reports for different countries so need to have various bank holidays not just UK. In SAP function modules handle this. Has anyone designed a solution to cater for this situation in a universe ?
    Thanks in advance
    M

    Hi,
    I assume you mean SAP R/3 (ECC) when you write SAP and SAP BW.
    Are you using BW? If so, I would load the data into SAP BW, create a query using customer exit variables and build your universe on top of that...
    -J

  • Add number of business days to date field

    Hello, I noticed that there is not much discussion in the forum surrounding u201Cbusiness daysu201D so I hope this post/discussion/solution contributes to the content of this forum.
    I am using the following 3 formulas to try to Add number of business days (based upon a table field) to a specified date:
    1. Variable name = SetVar
    //Set Variable for Add Business Days:
    DateVar Array Holidays;
    DateVar Target:= CDate({TMS_MOVEMENT_EVT.EVT_DATE}); // Put your field name in here
    NumberVar Add:=  {DTCI_DOD_TRANS.TRANS}; // put the number of days here to add (a positive number)
    NumberVar Added := (0);
    2. Variable name = AddBizDays
    //Adding Business Days:
    EvaluateAfter({@SetVar});
    WHILE Added < Add
    Do (target := target +1;
        if dayofweek (target) in 2 to 6 and not (target in holidays)
            then Added:=Added+1
            else Added:=Added);
    Target
    3. Variable name = HOLIDAYS
    //Holiday Array Formula for the report Header:
    BeforeReadingRecords;
    DateVar Array Holidays := [
    Date (2003,12,25),   // you can put in as many lines for holidays as you want. 
    Date (2003,12,31)
    0
    I am successfully getting my data needed to make the necessary calculations and variable assignmentsu2026 I believe that my ISSUE is that I am not sure where to place these formulas into my report so they assign the variables and execute properly when previewing my report. I am curious if that is my issue, and if so, can someone provide me direction on where to put each of these formulas in my report.
    Currently, when I try to preview the report, I get the following Crystal Reports Error:  -u201CA number, currency amount, Boolean, date, time, date-time, or string is expected here.u201D
    Then Crystal automatically opens the AddBizDays formula and highlights the word added, see below RE: u201CWHILE Addedu201D
    For reference, my report has 3 groups, and I am displaying all of my output information (and locating my formulas) in the group footer #3 report section. I have moved them around to other report sections/groups/placements, but to no success.
    Thanks so much.
    Best, Matt

    I worked this out... FYI - for the benefit of all forum users:
    ADDING BUSINESS DAYS TO A CERTAIN DATE (excluding weekends and holidays)
    1. Variable name = AddBizDays
    //Adding Business Days:
    WhileReadingRecords;
    DateVar Array Holidays;
    DateVar Target:= CDate(); // Put your field name in here
    NumberVar Add:=  ; // put the number of days here to add (a positive number)
    NumberVar Added := (0);
    WHILE Added < Add
    Do (target := target +1;
        if dayofweek (target) in 2 to 6 and not (target in holidays)
            then Added:=Added+1
            else Added:=Added);
    Target
    2. Variable name = HOLIDAYS
    //Holiday Array Formula for the report Header:
    BeforeReadingRecords;
    DateVar Array Holidays := [
    Date (2003,12,25), // you can put in as many lines for holidays as you want.
    Date (2003,12,31)
    0
    ...too bad i don't get forum points for sharing this solution.
    Special thanks to KenHamady.com -- for sharing this solution.
    Sincerely,
    Matt

  • How can i find the 1st business day of the week ?

    Hi,
    How can i find the 1st business day of the week excluding saturaday,sunday and holidays? i have holiday table which contains the columns name HolidayDate and HolidayDescription.
    Ex:
    10-1-2011 is monday(i.e) 1st business day.check If it is in holiday table,then return the result as 11-1-2011 else return the result as 11-1-2011(which is the first business day of this week).
    Can anyone tell me the Query to solve it?

    Does this help:
    SQL> ed
    Wrote file afiedt.buf
      1  with t as (SELECT TRUNC(SYSDATE,'IW') holiday FROM dual
      2  UNION SELECT TRUNC(SYSDATE + 7,'IW') from dual)
      3  SELECT MIN(Dat),wk FROM
      4  (SELECT TO_CHAR(dat,'IW') wk,dat FROM
      5  (SELECT dat + lvl dat FROM
      6  (SELECT TRUNC(SYSDATE,'RRRR') dat, level - 1 lvl
      7  FROM dual
      8  CONNECT BY level <= TO_DATE('31-DEC'||TO_CHAR(SYSDATE,'RRRR')) - TRUNC(SYSDATE,'RRRR'))
      9  ) x
    10  WHERE x.dat NOT IN (select holiday from t))
    11  WHERE TO_CHAR(Dat,'DY') <> 'SAT'
    12  AND TO_CHAR(dat,'DY') <> 'SUN'
    13* group by wk
    SQL> /
    MIN(DAT)  WK
    04-JAN-11 01  -- since 03-JAN-2011 is in holiday list, 04 is taken as first business day of first week
    11-JAN-11 02  -- similar to week 1
    17-JAN-11 03
    24-JAN-11 04
    31-JAN-11 05
    07-FEB-11 06
    14-FEB-11 07
    21-FEB-11 08
    28-FEB-11 09
    07-MAR-11 10
    14-MAR-11 11
    21-MAR-11 12
    28-MAR-11 13
    04-APR-11 14
    11-APR-11 15
    18-APR-11 16
    25-APR-11 17
    02-MAY-11 18
    09-MAY-11 19
    16-MAY-11 20
    23-MAY-11 21
    30-MAY-11 22
    06-JUN-11 23
    13-JUN-11 24
    20-JUN-11 25
    27-JUN-11 26
    04-JUL-11 27
    11-JUL-11 28
    18-JUL-11 29
    25-JUL-11 30
    01-AUG-11 31
    08-AUG-11 32
    15-AUG-11 33
    22-AUG-11 34
    29-AUG-11 35
    05-SEP-11 36
    12-SEP-11 37
    19-SEP-11 38
    26-SEP-11 39
    03-OCT-11 40
    10-OCT-11 41
    17-OCT-11 42
    24-OCT-11 43
    31-OCT-11 44
    07-NOV-11 45
    14-NOV-11 46
    21-NOV-11 47
    28-NOV-11 48
    05-DEC-11 49
    12-DEC-11 50
    19-DEC-11 51
    26-DEC-11 52
    52 rows selected.
    SQL>

  • Calculating Business Days(Start_dt - End_dt)

    Hi Friends,
    Could anyone of you help me to find out the business days(Excluding Saturdays and Sundays) between two dates.
    The difference should be calculated of both the Start_dt and End_dt values truncated. The result should be calculated and stored according to business days, it means weekend days are to be ignored.
    create table sample (id number,start_dt date,end_dt date). The table values are as follows;
    ID ; start_dt ; End_dt
    1 ; 08-02-2012 ; 15-02-2012
    2 ; 30-12-2011 ; 15-02-2012
    My output should be;
    ID ; start_dt ; End_dt ; Expected Business Days (Excluding Weekends)
    1 ; 08-02-2012 ; 15-02-2012 ; 4
    2 ; 30-12-2011 ; 15-02-2012 ; 33
    Please note that, the Start Date and End Date can be any date from any year. Please help me on this.
    Regards,
    Williams.
    Edited by: Williams on Feb 8, 2012 6:28 PM
    Edited by: Williams on Feb 8, 2012 6:29 PM

    Here's my first cut at it.
    SQL> WITH sample AS
      2  (
      3     SELECT 1 AS id, TO_DATE('08-02-2012','DD-MM-YYYY') AS start_dt, TO_DATE('15-02-2012','DD-MM-YYYY') AS end_dt FROM DUAL UNION ALL
      4     SELECT 2 AS id, TO_DATE('30-12-2011','DD-MM-YYYY') AS start_dt, TO_DATE('15-02-2012','DD-MM-YYYY') AS end_dt FROM DUAL
      5  )
      6  /* END SAMPLE DATA */
      7  SELECT id
      8       , start_dt
      9       , end_dt
    10       , COUNT(*)
    11  FROM   sample
    12  JOIN   ( /* Exclude Weekends */
    13           SELECT dt
    14           FROM  ( /* Generate a range that includes all days */
    15                   SELECT min_start_dt + (LEVEL - 1) AS dt
    16                        , TO_CHAR
    17                          ( min_start_dt + (LEVEL - 1)
    18                          , 'fmDAY'
    19                          , 'NLS_DATE_LANGUAGE=AMERICAN'
    20                          ) AS dy
    21                   FROM   ( SELECT MIN(start_dt) AS min_start_dt
    22                                 , MAX(end_dt)   AS max_end_dt
    23                            FROM   sample
    24                          )
    25                   CONNECT BY LEVEL <= max_end_dt - min_start_dt + 1
    26                 )
    27           WHERE dy NOT IN ('SATURDAY','SUNDAY')
    28         ) dys ON dys.dt BETWEEN start_dt AND end_dt
    29  GROUP BY id
    30         , start_dt
    31         , end_dt
    32  /
            ID START_DT            END_DT                COUNT(*)
             2 12/30/2011 00:00:00 02/15/2012 00:00:00         34
             1 02/08/2012 00:00:00 02/15/2012 00:00:00          6
    2 rows selected.I got different results then you though. Can you say why your counts are what they are?

  • Inconsistency between get-childitem -include and -exclude parameters

    Hi,
    Powershell 2.0
    Does anyone else consider this a minor design bug in the Get-ChildItem command?  
    # create dummy files
    "a","b","c" | % {$null | out-file "c:\temp\$_.txt"}
    # this "fails", returns nothing
    get-childitem c:\temp -include a*,b*
    # this "works", returns desired files
    get-childitem c:\temp\* -include a*,b*
    # this "works", excludes undesired files
    get-childitem c:\temp -exclude a*,b*
    # this "fails", excludes undesired files BUT RECURSES sub-directories
    get-childitem c:\temp\* -exclude a*,b*
    I'm writing a wrapper script around the GCI cmdlet, but the inconsistency between the two parameters is problematic.  My end user will surely just type a path for the path parameter, then wonder why -include returned nothing.  I can't unconditionally
    add an asterisk to the path parameter, since that messes up the exclude output.
    I'm just wondering why Microsoft didn't make the parameter interaction consistent???  
    # includes desired files in the specified path
    get-childitem -path c:\temp -include a*,b*
    # excludes undesired files in the specified path
    get-childitem -path c:\temp -exclude a*,b*
    # combine both options
    get-childitem -path c:\temp -include a*,b* -exclude *.log,*.tmp
    # same as above, the asterisk doesn't matter
    get-childitem -path c:\temp\* -include a*,b*
    get-childitem -path c:\temp\* -exclude a*,b*
    get-childitem -path c:\temp\* -include a*,b* -exclude *.log,*.tmp
    # same as above, but explicitly recurse if that's what you want
    get-childitem -path c:\temp\* -include a*,b* -recurse
    get-childitem -path c:\temp\* -exclude a*,b* -recurse
    get-childitem -path c:\temp\* -include a*,b* -exclude *.log,*tmp -recurse
    If I execute the "naked" get-childitem command, the asterisk doesn't matter...
    # same results
    get-childitem c:\temp
    get-chileitem c:\temp\*
    If this isn't considered a bug, can you explain why the inconsistency between the two parameters when combined with the -path parameter?
    Thanks,
    Scott

    The Get-ChildItem cmdlet syntax is horrific for advanced use. It's not a bug in the classic sense, so you shouldn't call it that. However, feel free to call it awful, ugly, disastrous, or any other deprecatory adjective you like - it really is
    nasty.
    Get-ChildItem's unusual behavior is rooted in one of the more 'intense' dialogues between developers and users in the beta period. Here's how I recall it working out; some details are a bit fuzzy for me at this point.
    Get-ChildItem's original design was as a tool for enumerating items in a namespace -
    similar to but not equivalent to dir and
    ls. The syntax and usage was going to conform to standard PowerShell (Monad at the time) guidelines.
    In a nutshell, what this means is that the Path parameter would have truly just meant Path - it would not have been usable as a combination path specification and result filter, which it is now. In other words
    (1) dir c:\temp
    means you wanted to return children of the container c:\temp
    (2) dir c:\temp\*
    means you wanted to return children of all containers inside
    c:\temp. With (2), you would never get c:\tmp\a.txt returned, since a.txt is not a container.
    There are reasons that this was a good idea. The parameter names and filtering behavior was consistent with the evolving PowerShell design standards, and best of all the tool would be straightforward to stub in for use by namespace
    providers consistently.
    However, this produced a lot of heated discussion. A rational, orthogonal tool would not allow the convenience we get with the dir command for doing things like this:
    (3) dir c:\tmp\a*.txt
    Possibly more important was the "crash" factor.  It's so instinctive for admins to do things like (3) that our fingers do the typing when we list directories, and the instant failure or worse, weird, dissonant output we would get with a more pure Path
    parameter is exactly like slamming into a brick wall.
    At this point, I get a little fuzzy about the details, but I believe the Get-ChildItem syntax was settled on as a compromise that wouldn't derail people expecting files when they do (3), but would still allow more complex use.  I think that this
    is done essentially by treating all files as though they are containers for themselves. This saves a lot of pain in basic use, but introduces other pain for advanced use.
    This may shed some light on why the tool is a bit twisted, but it doesn't do a lot to help with your particular wrapping problem. You'll almost certainly need to do some more complicated things in attempting to wrap up Get-ChildItem. Can you describe some
    details of what your intent is with the wrapper? What kind of searches by what kind of users, maybe? With those details, it's likely people can point out some specific approaches that can give more consistent results.

  • Calculating Business Days in a Date Range

    I have two questions:
    1. Does anyone know a better formula for calculating business days in totals?
    I am currently using the formula in https://www.sdn.sap.com/irj/sdn/go/portal/prtroot/docs/library/uuid/701a52c3-6b1e-2b10-21b3-a6e101be1a0f
    I tailored to my needs.  However, there are still a lot of manual maintenance every year. 
    2. I have many reports that need the formula.  It is very consuming to update the formula in each report.  Does anyone know a better way to do it? 
    I use Crystal XI. 11.0.0.895.  We do have a Crystal Enterprise server hosted in another department.

    Not sure if this is any simpler but you could save this as a custom function, that way you will have to modify it once a year for the holidays.
    numbervar days;
    datevar date1 := minimum({?My Parameter});
    datevar date2 := maximum({?My Parameter});
    days := DateDiff ("d", date1, date2) -
    DateDiff ("ww", date1, date2, crSaturday) -
    DateDiff ("ww", date1, date2, crSunday);    // this will give you the number of business days
                                                        // (excluding Saturdays and Sundays) for a given date range.
    // then, for each holiday, you can enter lines like this
    if date(2008,01,01) in {?My Parameter} then days := days - 1;
    // The final tally of DAYS should give you the total business days in a date range.
    totext(days,0);
    where {?My Parameter} is the date range.

  • Calculate business day between two dates

    Hi Guys
    I need the count of business days between two  dates
    Date1, Date2 i need the count only business day (exclude sartuday&sunday)
    If date1 is null or nothing i need to pass 0
    If date2 is null or nothing i need to pass 0
    help on this

    Hi,
    To achive this within SSRS, go to the report code window and add the below
    Function getBusinessDaysCount(ByVal tFrom As Date, ByVal tTo As Date) As Integer
    Dim tCount As Integer
    Dim tProcessDate As Date = tFrom
    For x as Integer= 1 To DateDiff(DateInterval.Day, tFrom, tTo) + 1
    If Not (tProcessDate.DayOfWeek = DayOfWeek.Saturday Or tProcessDate.DayOfWeek = DayOfWeek.Sunday) Then
    tCount = tCount + 1
    End If
    tProcessDate = DateAdd(DateInterval.Day, 1, tProcessDate)
    Next
    Return tCount
    End Function
    In the textbox where you need to display the value, add the below expression
    =Code.getBusinessDaysCount(parameters!StartDate.Value,parameters!EndDate.Value)
    It is assumed the you want to pass the two days from parameters named Startdate and EndDate. If not, modify the expression with required values.
    Regards
    Please click "Mark as Answer" if this resolves your problem or "Vote as Helpful" if you find it helpful. BH

  • Calculate "Business Days" and account for holidays

    I have played with Date math based on what I have found for documentation, and adding an arbitrary number of days is pretty easy. But what about adding an arbitrary number of business days? I found a web site that talks about "Next business day",
    which could be adapted I am sure, but it only accounts for weekends. I want to calculate the date an arbitrary number of business days from a provided date. So, +3 business days calculated from a Monday should produce the date of the following Thursday,
    and calculated from a Friday should produce the date of the next Wednesday. And calculated from Friday Sept 4, 2015 (Friday before Labor Day) should produce Thursday Sept 10, 2015.
    Given that Windows is very business focused, I wonder if there is some nice hidden .NET functionality to calculate business days based on holidays as well? I know, some offices might give extra days off, four day weekends, etc. But those would be edge case
    enough to be safely ignorable for my purposes. Indeed, even holidays could probably be ignored, but if there is a quick approach I would rather use it. If I would need to code some sort of Exchange calendar scraper or some such, I'll live with just accounting
    for weekends. ;)

    You can pull holiday info from outlook.hol file and do the date math based on it. It won't be 100% reliable though. Not all the holidays listed in calendar are non-business days (not in all countries at least). International support may also present additional
    issues: in some countries it is a common practice to "move" weekend days to fill a single day gap between holidays and weekend (which screws up next business day calc anyway, regardless of holiday info :-). Not to mention all the possible industry-wide
    or company specific policies regarding working days.
    Gleb.

Maybe you are looking for