Możesz to wszystko zrobić w SQL:
WITH dates ( dt, lvl ) AS (
SELECT CAST( TRUNC( :your_date ) AS DATE ), 0 FROM DUAL
UNION ALL
SELECT CAST( dt - INTERVAL '1' DAY AS DATE ),
CASE
WHEN ( dt - INTERVAL '1' DAY ) - TRUNC( dt - INTERVAL '1' DAY, 'IW' ) >= 5
OR hol_date IS NOT NULL
THEN lvl
ELSE lvl + 1
END
FROM dates d
LEFT OUTER JOIN
holidays h
ON ( d.dt - INTERVAL '1' DAY = h.hol_date )
WHERE lvl < 2
)
SELECT *
FROM dates
PIVOT ( MAX( dt ) FOR lvl IN ( 1 AS DATE24, 2 AS DATE48 ) );
(Uwaga:używanie CAST
nie powinno być konieczne, ale bez otrzymuję ORA-01790: expression must have same datatype as corresponding expression
)
Lub jako funkcja:
CREATE OR REPLACE FUNCTION F_HOL_CHECK_S_NS (
i_hol_date DATE,
i_S_NS NUMBER
) RETURN DATE
AS
p_date DATE;
BEGIN
WITH dates ( dt, lvl ) AS (
SELECT CAST( TRUNC( i_hol_date ) AS DATE ), 0 FROM DUAL
UNION ALL
SELECT CAST( dt - INTERVAL '1' DAY AS DATE ),
CASE
WHEN ( dt - INTERVAL '1' DAY ) - TRUNC( dt - INTERVAL '1' DAY, 'IW' ) >= 5
OR hol_date IS NOT NULL
THEN lvl
ELSE lvl + 1
END
FROM dates d
LEFT OUTER JOIN
holidays h
ON ( d.dt - INTERVAL '1' DAY = h.hol_date )
WHERE lvl < i_s_ns
)
SELECT dt
INTO p_date
FROM dates
WHERE lvl = i_s_ns;
RETURN p_date;
END;
/