Работа с праздничным столом в целом работает, однако требует определенных затрат на обслуживание, поскольку некоторые праздничные дни движутся.Например, День благодарения - 4-й четверг ноября, т.е. он варьируется с 22 ноября по 28 ноября.
Вы также можете использовать встроенный планировщик Oracle.Обычно он используется для управления SCHEDULER JOBS
, но я не вижу причин, по которым его нельзя использовать для чего-то другого.
Сначала создайте список федеральных праздников, например, так:
BEGIN
DBMS_SCHEDULER.CREATE_SCHEDULE(schedule_name => 'CHRISTMAS', repeat_interval => 'FREQ=YEARLY;INTERVAL=1;BYDATE=1225', comments => 'December 25');
DBMS_SCHEDULER.CREATE_SCHEDULE(schedule_name => 'COLUMBUS_DAY', repeat_interval => 'FREQ=MONTHLY;BYMONTH=OCT;BYDAY=2 MON', comments => '2nd Monday in October');
DBMS_SCHEDULER.CREATE_SCHEDULE(schedule_name => 'INDEPENDENCE_DAY', repeat_interval => 'FREQ=YEARLY;INTERVAL=1;BYDATE=0704', comments => 'July 4');
DBMS_SCHEDULER.CREATE_SCHEDULE(schedule_name => 'MARTIN_LUTHER_KING_DAY', repeat_interval => 'FREQ=MONTHLY;BYMONTH=JAN;BYDAY=3 MON', comments => '3rd Monday in January');
DBMS_SCHEDULER.CREATE_SCHEDULE(schedule_name => 'MEMORIAL_DAY', repeat_interval => 'FREQ=MONTHLY;BYMONTH=MAY;BYDAY=-1 MON', comments => 'Last Monday of May');
DBMS_SCHEDULER.CREATE_SCHEDULE(schedule_name => 'NEW_YEARS_DAY', repeat_interval => 'FREQ=YEARLY;INTERVAL=1;BYDATE=0101', comments => 'January 1');
DBMS_SCHEDULER.CREATE_SCHEDULE(schedule_name => 'THANKSGIVING', repeat_interval => 'FREQ=MONTHLY;BYMONTH=NOV;BYDAY=4 THU', comments => '4th Thursday in November');
DBMS_SCHEDULER.CREATE_SCHEDULE(schedule_name => 'WASHINGTONS_BIRTHDAY', repeat_interval => 'FREQ=MONTHLY;BYMONTH=FEB;BYDAY=3 MON', comments => '3rd Monday in February');
DBMS_SCHEDULER.CREATE_SCHEDULE(schedule_name => 'WEEKEND', repeat_interval => 'FREQ=DAILY;INTERVAL=1;BYDAY=SAT,SUN');
-- Combined schedule for all federal holidays
DBMS_SCHEDULER.CREATE_SCHEDULE(schedule_name => 'FEDERAL_HOLIDAYS', repeat_interval => 'FREQ=DAILY;INTERSECT=CHRISTMAS,INDEPENDENCE_DAY,MARTIN_LUTHER_KING_DAY,MEMORIAL_DAY,NEW_YEARS_DAY,THANKSGIVING,WASHINGTONS_BIRTHDAY');
END;
/
Посмотрите на Синтаксис календаря , чтобы увидеть, как нужно указать repeat_interval
.
Затем вы можете использовать процедуру DBMS_SCHEDULER.EVALUATE_CALENDAR_STRING
, чтобы получить вашу дату:
CREATE OR REPLACE FUNCTION LAST_BUSINESS_DAY(today IN TIMESTAMP DEFAULT SYSTIMESTAMP) RETURN TIMESTAMP AS
return_date_after TIMESTAMP := TRUNC(today);
next_run_date TIMESTAMP;
BEGIN
LOOP
DBMS_SCHEDULER.EVALUATE_CALENDAR_STRING('FREQ=DAILY;INTERVAL=1;EXCLUDE=FEDERAL_HOLIDAYS,WEEKEND', NULL, return_date_after, next_run_date);
EXIT WHEN next_run_date >= LAST_DAY(TRUNC(today));
return_date_after := next_run_date;
END LOOP;
RETURN return_date_after;
END LAST_BUSINESS_DAY;