Я попытаюсь подсчитать количество выходных дней с аналогичным l oop:
WHILE (v_copy > 0) LOOP
end_date := end_date + 1;
IF to_char(end_date, 'fmdy') IN ('sat', 'sun') THEN
end_date := end_date + 1;
ELSE
v_copy := v_copy - 1;
END IF;
END LOOP;
И затем после цикла вы можете подсчитать количество выходных в таблице, которые находятся после start_date
и end_date
, а не в ('sat', 'sun')
.
SELECT COUNT(*) INTO v_custom_cnt
FROM holiday_table
WHERE to_char(holidays, 'fmdy') not in ('sat', 'sun') AND
holidays BETWEEN start_date AND end_date;
Теперь добавьте этот номер к вашему end_date
, и вы получите дату n-го рабочего дня. Конечно, перед возвратом проверьте, находится ли новый end_date
в ('sat', 'sun')
.
end_date := end_date + v_custom_cnt;
IF to_char(holidays, 'fmdy') in ('sat', 'sun') THEN
end_date := next_day(end_date, 'monday');
END IF;
Наконец, end_date
- это дата n-го рабочего дня.
CREATE OR REPLACE FUNCTION add_n_working_days (
start_date DATE,
working_days PLS_INTEGER
) RETURN DATE AS
end_date DATE := start_date;
counter PLS_INTEGER := 0;
v_copy PLS_INTEGER := working_days;
v_custom_cnt INTEGER := 0;
BEGIN
IF working_days = 0 THEN
end_date := start_date;
ELSIF to_char(start_date, 'fmdy') IN ('sat', 'sun') THEN
end_date := next_day(start_date, 'monday');
END IF;
WHILE (v_copy > 0) LOOP
end_date := end_date + 1;
IF to_char(end_date, 'fmdy') IN ('sat', 'sun') THEN
end_date := end_date + 1;
ELSE
v_copy := v_copy - 1;
END IF;
END LOOP;
SELECT COUNT(*) INTO v_custom_cnt
FROM holiday_table
WHERE to_char(end_date, 'fmdy') NOT IN ('sat', 'sun')
AND holidays BETWEEN start_date AND end_date;
end_date := end_date + v_custom_cnt;
IF to_char(end_date, 'fmdy') IN ('sat', 'sun') THEN
end_date := next_day(start_date, 'monday');
END IF;
RETURN end_date;
END add_n_working_days;
Не проверено на 100%