也许有更简单的方法可以做到这一点,但我写了两个选项。
如果您想在一个月内第 n 次出现给定的工作日,您可以使用以下代码:
declare
l_month_year char(6):= '012016'; -- JAN-2016
l_date date;
begin
with base as (
select to_date(ltrim(to_char(level, '00'))||l_month_year, 'ddmmyyyy') examdate,
to_char(to_date(ltrim(to_char(level, '00'))||l_month_year, 'ddmmyyyy'), 'd') dayofweek,
count(*) over(partition by to_char(to_date(ltrim(to_char(level, '00'))||l_month_year, 'ddmmyyyy'), 'd') order by level rows between unbounded preceding and current row) ocurrence
from dual
connect by level <= to_number(to_char(last_day(to_date(l_month_year, 'mmyyyy')), 'dd'))
)
select examdate
into l_date
from base
where ocurrence = 1 and dayofweek = 2;
Dbms_Output.put_line(to_char(l_date, 'dd-MON-yyyy'));
end;
如果您想要每月第 n 周的给定星期几中的日期,代码如下:
declare
l_month_year char(6):= '012016'; -- JAN-2016
l_date date;
begin
with base as (
select to_date(ltrim(to_char(level, '00'))||l_month_year, 'ddmmyyyy') examdate,
to_char(to_date(ltrim(to_char(level, '00'))||l_month_year, 'ddmmyyyy'), 'd') dayofweek,
to_char(to_date(ltrim(to_char(level, '00'))||l_month_year, 'ddmmyyyy'), 'ww') - min(to_char(to_date(ltrim(to_char(level, '00'))||l_month_year, 'ddmmyyyy'), 'ww')) over() + 1 weekofmonth
from dual
connect by level <= to_number(to_char(last_day(to_date(l_month_year, 'mmyyyy')), 'dd'))
)
select examdate
into l_date
from base
where weekofmonth = 1 and dayofweek = 2;
Dbms_Output.put_line(to_char(l_date, 'dd-MON-yyyy'));
exception when no_data_found then
Dbms_Output.put_line('there is not a day 2 in week 1 of '||to_char(to_date(l_month_year, 'mmyyyy'), 'Month-YYYY'));
end;
请注意,对于 2016 年 2 月,在第一种情况下会输出“01-FEV-2016”,因为它是第一周的星期一。第二种方式,输出为“08-FEV-2016”:二月第二次出现的星期一。