'Determine holidays in Oracle
Is there a default function in Oracle that allows you to pass the date as the parameter, and it returns whether it is a US holiday or not?
something like
IS_HOLIDAY(:DATEINPUT)
I need to do this without a stored procedure. In my select statement, what I'd like to do is filter out data based on holday, in my where clause.
Please help.
Solution 1:[1]
Here is a function I wrote to test if us holiday. Note if you need first business day after a govt holiday or other holiday then you can use second function as well.
create or replace
FUNCTION IS_HOLIDAY(V_DT DATE) RETURN VARCHAR2 AS
RET VARCHAR2(1);
V_MONTH VARCHAR2(2);
V_DAY VARCHAR2(2);
V_YEAR VARCHAR2(4);
MLK DATE;
WASHINGTON DATE;
MEMORIAL DATE;
COLUMBUS DATE;
THANKSGIVING DATE;
BEGIN
RET:='F';
SELECT TO_CHAR(V_DT,'YYYY') INTO V_YEAR FROM DUAL;
SELECT TO_CHAR(V_DT,'MM') INTO V_MONTH FROM DUAL;
SELECT TO_CHAR(V_DT,'dd') INTO V_DAY FROM DUAL;
SELECT NEXT_DAY(TO_DATE(TO_CHAR(SYSDATE,'YYYY')||'0201','YYYYMMdd')-1,'MON')+14 INTO WASHINGTON FROM DUAL;
SELECT NEXT_DAY(TO_DATE(TO_CHAR(SYSDATE,'YYYY')||'0101','YYYYMMdd')-1,'MON')+14 INTO MLK FROM DUAL;
SELECT NEXT_DAY(TO_DATE(TO_CHAR(SYSDATE,'YYYY')||'0201','YYYYMMdd')-1,'MON')+14 INTO WASHINGTON FROM DUAL;
SELECT NEXT_DAY(LAST_DAY(TO_DATE(TO_CHAR(SYSDATE,'YYYY')||'0501','YYYYMMdd'))-7,'MONDAY')INTO MEMORIAL FROM DUAL;
SELECT NEXT_DAY(TO_DATE(TO_CHAR(SYSDATE,'YYYY')||'1001','YYYYMMdd')-1,'MON')+7 INTO COLUMBUS FROM DUAL;
SELECT NEXT_DAY(TO_DATE(TO_CHAR(SYSDATE,'YYYY')||'1101','YYYYMMdd')-1,'THURSDAY')+21 INTO THANKSGIVING FROM DUAL;
IF(TRUNC(V_DT) = TRUNC(MLK) )THEN RET:='T';
ELSIF(TRUNC(V_DT)=TRUNC(WASHINGTON))THEN RET :='T';
ELSIF(TRUNC(V_DT)=TRUNC(MEMORIAL) )THEN RET:='T';
ELSIF(TRUNC(V_DT)=TRUNC(COLUMBUS)) THEN RET:= 'T';
ELSIF(TRUNC(V_DT)=TRUNC(THANKSGIVING)) THEN RET:='T';
ELSIF(V_MONTH ='01' AND V_DAY='01') THEN RET:='T'; --NEW YEARS
ELSIF(V_MONTH='07' AND V_DAY='04') THEN RET:='T';
ELSIF(V_MONTH='09' AND V_DAY='02') THEN RET:='T';
ELSIF(V_MONTH='11' AND V_DAY='11') THEN RET:='T';
ELSIF(V_MONTH='12' AND V_DAY='25') THEN RET:='T';
END IF;
RETURN RET;
END DIS_IS_HOLIDAY;
This next function will find first business day given holiday
create or replace
FUNCTION first_business_day (v_dt DATE)
RETURN DATE
IS
return_dt DATE;
BEGIN
SELECT CASE
WHEN (CASE
WHEN( TO_CHAR (TRUNC (V_DT, 'MM'), 'DY') IN
('SAT', 'SUN'))
THEN
NEXT_DAY (TRUNC (v_dt, 'MM'), 'MON')
ELSE
TRUNC (V_DT, 'MM')
END) IS NOT NULL AND DIS_IS_HOLIDAY(V_DT)='T'
THEN
CASE
WHEN TO_CHAR (TRUNC (v_dt, 'MM') + 1, 'DY') IN
('SAT', 'SUN')
THEN
NEXT_DAY (TRUNC (v_dt, 'MM') + 1, 'MON')
ELSE
TRUNC (v_dt, 'MM') + 1
END
ELSE
CASE
WHEN TO_CHAR (TRUNC (v_dt, 'MM'), 'DY') IN ('SAT', 'SUN')
THEN
NEXT_DAY (TRUNC (v_dt, 'MM'), 'MON')
ELSE
TRUNC (v_dt, 'MM')
END
END
INTO return_dt
FROM DUAL;
RETURN return_dt;
END;
Solution 2:[2]
Couldn't you store the US holidays in a different table, then join it?
I'm sure there is free public data out there that will provide what you need. For example, this site displays all US bank holidays from 2012 to 2020: https://gist.github.com/shivaas/4758439
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | user2225399 |
| Solution 2 | Sun |
