对于这些棘手的相对日期问题,一种方便的技术是使用 DBMS_Schedular 日历语法,我在此处和此处写过。
DBMS_Scheduler 具有非常全面的日历语法,非常适合复杂的日历规范(一旦您习惯了它),并且 Evaluate_Calendar_String 函数返回在提供的日期之后满足计划规范的下一个时间戳。
这是代码:
create or replace type timestamp_table_type
is
table of timestamp;
/
create or replace function
list_of_dates (
calendar_string varchar2,
start_date TIMESTAMP WITH TIME ZONE,
stop_date TIMESTAMP WITH TIME ZONE)
return
timestamp_table_type
pipelined
is
l_return_date_after TIMESTAMP WITH TIME ZONE := start_date - interval '1' second;
l_next_run_date TIMESTAMP WITH TIME ZONE;
begin
loop
DBMS_SCHEDULER.EVALUATE_CALENDAR_STRING(
calendar_string => list_of_dates.calendar_string,
start_date => list_of_dates.start_date,
return_date_after => l_return_date_after,
next_run_date => l_next_run_date);
exit when list_of_dates.l_next_run_date > coalesce(list_of_dates.stop_date,date '9999-12-31');
pipe row (list_of_dates.l_next_run_date);
list_of_dates.l_return_date_after := list_of_dates.l_next_run_date;
end loop;
end;
/
我认为每个月的第三个星期五是:
begin
dbms_scheduler.create_schedule(
schedule_name => 'THIRD_THU_OF_EVERY_MONTH',
repeat_interval => 'FREQ=MONTHLY;BYDAY=5;BYSETPOS=3');
end;
/
select *
from table(
list_of_dates(
'THIRD_THU_OF_EVERY_MONTH',
sysdate ,
null));
不幸的是,恐怕我没有方便的 Oracle 系统来测试它。