在工作中可能会有这种需求,想要根据开始时间和延迟特定工作日天数获得延迟后的具体日期(不包含周末和节假日
),例如:依据日期2012-08-27获取延迟5个工作日后的日期,得到具体日期2012-09-03;
那这种情况应该如何处理呢?
本文将从数据库角度来解决这一问题,当然利用代码在逻辑中更容易实现哦!!
注:本文应用是oracle10;
第一步:
创建一个表格holiday用于灵活存放节假日日期(周末除外),如果和周末日期重复,则无需添加到该表格中:
create table HOLIDAY ( ID VARCHAR2(45) not null, HL_DATE DATE, HL_DESC VARCHAR2(500), REMARK VARCHAR2(500), constraint PK_HOLIDAY primary key (ID) ); comment on table HOLIDAY is '节假日日期表(不含周末)'; comment on column HOLIDAY.ID is '节假日编号'; comment on column HOLIDAY.HL_DATE is '节假日期'; comment on column HOLIDAY.HL_DESC is '假日说明'; comment on column HOLIDAY.REMARK is '备注';
添加一些测试数据:
ID HL_DATE HL_DESC
1 2012-9-29 十一
2 2012-10-1 十一
3 2012-10-2 十一
4 2012-10-3 十一
5 2012-10-4 十一
6 2012-10-5 十一
7 2012-9-3 测试
8 2012-9-5 测试
9 2012-9-6 测试
第二步:写个函数用以获取两个日期之间的周末天数,如下:
create or replace function weekend_count(startdate date,enddate date) return number /**返回两个时间段内的周末天数,开始日期不计算在内*/ is weekend_num number:=0; tempdate date; begin tempdate:=startdate+1; while tempdate<=enddate loop weekend_num:=weekend_num+(case when to_char(tempdate,'day') in('星期六','星期日') then 1 else 0 end); tempdate:=tempdate+1; end loop; return weekend_num; end;
第三步:编写函数用以获取指定日期延迟特定工作日以后的具体日期,如下:
create or replace function getDeferDate(startdate date,deferDay number) return date /**返回延期后的日期*/ is enddate date :=startdate+deferDay;--延期后的日期 holiday_num number:=0;--节假日天数 weekend_num number:=0;--周末天数 nonework_num number :=0;--非工作日天数 begin --获取周末天数 weekend_num:=weekend_count(startdate,enddate); --获取节假日天数 select nvl(count(1),0) into holiday_num from holiday a where a.hl_date is not null and a.hl_date between startdate and enddate; nonework_num:=weekend_num+holiday_num; if nonework_num !=0 then enddate :=getDeferDate(enddate,nonework_num); end if; return enddate; end;
第四步:实际应用,如下:
select getdeferdate(sysdate,5) deferdate from dual;
结果如下:
DEFERDATE
1 2012-9-4 16:12:53