需求:給定基準日期、方向 (前/後)、天數 N,回傳跳過週六、週日後的實際日期。節假日需另行維護表排除。
CREATE OR REPLACE PROCEDURE proc_CalculationWorkDate (
plan_date IN DATE, -- 基準日期
flag IN NUMBER, -- 1: 往前推, 0: 往後推
date_number IN NUMBER, -- 工作日天數
out_date OUT DATE -- 計算結果
) IS
dayOfWeek NUMBER := 0;
dates NUMBER := date_number;
i INT := 0;
j INT := 0;
BEGIN
IF flag = 1 THEN -- 往前推
WHILE i < date_number + 1 LOOP
SELECT TO_NUMBER(TO_CHAR(plan_date - i - j, 'D')) INTO dayOfWeek FROM dual;
IF dayOfWeek IN (1, 7) THEN -- 週日=1, 週六=7 (視 NLS_TERRITORY 而定)
dates := dates + 1;
j := j + 1;
ELSE
i := i + 1;
END IF;
END LOOP;
SELECT plan_date - dates INTO out_date FROM dual;
ELSIF flag = 0 THEN -- 往後推
WHILE i < date_number + 1 LOOP
SELECT TO_NUMBER(TO_CHAR(plan_date + i + j, 'D')) INTO dayOfWeek FROM dual;
IF dayOfWeek IN (1, 7) THEN
dates := dates + 1;
j := j + 1;
ELSE
i := i + 1;
END IF;
END LOOP;
SELECT plan_date + dates INTO out_date FROM dual;
END IF;
END;
/
VARIABLE v_result DATE;
EXEC proc_CalculationWorkDate(TO_DATE('2024-05-01','YYYY-MM-DD'), 0, 5, :v_result);
PRINT v_result; -- 2024-05-08 (跳過 5/4-5 週末)
TO_CHAR(...,'D') 回傳的星期數字受 NLS_TERRITORY 影響 (美制週日=1,ISO 週一=1),部署前請確認會話設定。HOLIDAY 表,查詢時再排除法定假日。