创建一个函数f_calcdate,用于工作日期的加减计算,具体要求:
1、输入,参数一:日期类型,参数二:数字型,表示工作日的个数
2、输出,日期类型
3、判断输入参数二的合法性,在-1000~1000之间:超出范围,函数返回1900-01-01
4、输入日期可以是节假日,但输出日期必须是工作日
5、当参数一位节假日,并且参数二为0时,函数返回下一个工作日前提中还有一个法定节假日表t_holiday,用于存放每年的法定节日(这个表里的记录是自己随便输入的 不一定非是五一、十一之类的)
表中有三个字段
节日 holiday date
节日说明 holiday_des varchar2(100)
节日类型 holiday_type number估计在函数中还需要访问这个表,表里存的日期也当做节假日来处理。
原题如上,刚才想了想没什么太好的思路,来这里发个帖,看看大家有什么解决办法没有。
谢谢了。
1、输入,参数一:日期类型,参数二:数字型,表示工作日的个数
2、输出,日期类型
3、判断输入参数二的合法性,在-1000~1000之间:超出范围,函数返回1900-01-01
4、输入日期可以是节假日,但输出日期必须是工作日
5、当参数一位节假日,并且参数二为0时,函数返回下一个工作日前提中还有一个法定节假日表t_holiday,用于存放每年的法定节日(这个表里的记录是自己随便输入的 不一定非是五一、十一之类的)
表中有三个字段
节日 holiday date
节日说明 holiday_des varchar2(100)
节日类型 holiday_type number估计在函数中还需要访问这个表,表里存的日期也当做节假日来处理。
原题如上,刚才想了想没什么太好的思路,来这里发个帖,看看大家有什么解决办法没有。
谢谢了。
呵呵 不用考虑农历 在这里 只有周六、周日、和t_holiday表中holiday字段存储都日期算作节假日2
应该是2010.5.3日吧? 我刚看日历5.2是周日
如果是实际使用,建议把节假日表换成工作日表
create table t_WORKDAY
(
NATIVEDAY date not null,--日期
DAYTYPE VARCHAR2(1),--类型,0为节假日,1为工作日
SUMMARY VARCHAR2(40),--日期说明
WORKDAYORDER NUMBER,--工作日序号
)
;
这样计算工作日会比较简单,有效
f_calcdate
(
pi_workday in date,
pi_count in number
)
return date
is
vd_date date;
vn_loop number;
begin
vd_date=pi_workday;
vn_loop:=pi_count;
loop --调整日期到工作日
exit when vd_date 不是节假日
vd_date :=vd_date+1;
end loop;
loop --计算工作日
exit when vn_loop=0;
if vn_loop>0 then --pi_count>0的话日期增,否则减
vd_date :=vd_date+1;
loop
exit when vd_date 不是节假日
vd_date :=vd_date+1;
end loop;
vn_loop:=vn_loop-1;
else
vd_date :=vd_date-1;
loop
exit when vd_date 不是节假日
vd_date :=vd_date-1;
end loop;
vn_loop:=vn_loop+1;
end;
end loop;
return vd_date;
end;
一些条件判断什么的就自己完善好了
return date is
v_date date;
v_sign number;
v_sign1 number;
begin
if p_days < -1000 or p_days > 1000 then
v_date := to_date('1900-01-01', 'yyyy-mm-dd');
else
v_date := p_date + p_days;
loop
-- 循环 如果日期不符合要求就加一天,直到日期是工作日为止。
select count(*) into v_sign from t_holiday where holiday = v_date;
v_sign1 := to_number(to_char(v_date, 'd'));
if v_sign = 0 and v_sign1 <> 6 and v_sign1 <> 7 then
--判断是否为工作日
exit;
end if;
v_date := v_date + 1;
end loop;
end if;
return v_date;end add_workday;
要计算p_date后的第p_days个工作日呢?
create or replace function f_calcdate
(
pi_workday in date,
pi_count in number
)
return date
is
vd_date date;
vn_loop number;
v_sign number;
v_sign1 number;
begin
vd_date=pi_workday;
vn_loop:=pi_count;
if pi_count < -1000 or pi_count > 1000 then
return to_date('1900-01-01', 'yyyy-mm-dd');
end if;
loop --调整日期到工作日
select count(*) into v_sign from t_holiday where holiday = vd_date;
v_sign1 := to_number(to_char(vd_date, 'd'));
if v_sign = 0 and v_sign1 <> 6 and v_sign1 <> 7 then
--判断是否为工作日
exit;
end if;
vd_date :=vd_date+1;
end loop;
loop --计算工作日
exit when vn_loop=0;
if vn_loop>0 then --pi_count>0的话日期增,否则减
vd_date :=vd_date+1;
loop
select count(*) into v_sign from t_holiday where holiday = vd_date;
v_sign1 := to_number(to_char(vd_date, 'd'));
if v_sign = 0 and v_sign1 <> 6 and v_sign1 <> 7 then
exit;
end if;
vd_date :=vd_date+1;
end loop;
vn_loop:=vn_loop-1;
else
vd_date :=vd_date-1;
loop
select count(*) into v_sign from t_holiday where holiday = vd_date;
v_sign1 := to_number(to_char(vd_date, 'd'));
if v_sign = 0 and v_sign1 <> 6 and v_sign1 <> 7 then
exit;
end if;
vd_date :=vd_date-1;
end loop;
vn_loop:=vn_loop+1;
end;
end loop;
return vd_date;
end;
子函数 计算下一个工作日(日期)
begin
loop
exit when 日期 在假日表中不存在
日期=日期+1;
end loop;
return 日期;
end;
begin
结果日期:=计算下一个工作日(日期);
for i in 1..天数-1 loop
结果日期:=计算下一个工作日(结果日期);
end loop;
return 结果日期;
end;
函数 f_calcdate(日期,天数)
子函数 计算下一个工作日(日期)
begin
loop
exit when 日期 在假日表中不存在
日期=日期+1;
end loop;
return 日期;
end;
begin
结果日期:=计算下一个工作日(日期);
for i in 1..天数-1 loop
结果日期:=计算下一个工作日(结果日期);
end loop;
return 结果日期;
end;
鼓励一下
补充两点哈
1
if v_sign = 0 and v_sign1 <> 6 and v_sign1 <> 7 then
应该改为
if v_sign = 0 and v_sign1 <> 7 and v_sign1 <> 1 then
2
题目里的功能5还没加进去
5、当参数一位节假日,并且参数二为0时,函数返回下一个工作日
return number is
--返回值是工作的总天数,包括工作日和假日。
v_alldays number := 0; --总天数
v_workdays number := 0; --工作日
v_date date := p_date;
v_sign number;
v_sign1 number;
begin
loop
--循环 当v_alldays=p_days时结束,记录此时得到的总天数,返回总天数。
v_date := v_date + 1;
select count(*) into v_sign from t_holiday where holiday = v_date;
v_sign1 := to_number(to_char(v_date, 'd'));
if v_sign = 0 and v_sign1 <> 6 and v_sign1 <> 7 and v_workdays = p_days then
--记录此时得到的总天数,返回总天数
v_alldays := v_alldays + 1;
exit;
else
if v_sign = 0 and v_sign1 <> 6 and v_sign1 <> 7 then
--不是节假日 总天数加1,工作天数加1
v_alldays := v_alldays + 1;
v_workdays := v_workdays + 1;
else
if v_sign <> 0 or v_sign1 = 6 or v_sign1 = 7 then
--是节假日 总天数加1,工作天数不加1
v_alldays := v_alldays + 1;
end if;
end if;
end if;
end loop;
return v_alldays - 1; --上面多算了一天
end js_days;然后在函数add_workday中调用上面的方法:
create or replace function add_workday(p_date date, p_days number)
return date is
v_date date;
v_sign number;
v_sign1 number;
begin
if p_days < -1000 or p_days > 1000 then
v_date := to_date('1900-01-01', 'yyyy-mm-dd');
else
v_date := p_date +js_days(p_date, p_days); --调用
loop
-- 循环 如果日期不符合要求就加一天,直到日期是工作日为止。
select count(*) into v_sign from t_holiday where holiday = v_date;
v_sign1 := to_number(to_char(v_date, 'd'));
if v_sign = 0 and v_sign1 <> 6 and v_sign1 <> 7 then
--判断是否为工作日
exit;
end if;
v_date := v_date + 1;
end loop;
end if;
return v_date;end add_workday;
请问一下哪位知道这是什么原因呢?为什吗不能直接比较
SQL> select * from t_holiday;HOLIDAY HOLIDAY_DES HOLIDAY_TYPE
-------------- ------------------------------ ------------
11-3月 -10 new 789
06-3月 -10 hello 123
08-3月 -10 woman 456
SQL> create or replace function f_calcdate
2 (
3 pi_workday in date,
4 pi_count in number
5 )
6 return date
7 is
8 vd_date date;
9 vn_loop number;
10 v_sign number;
11 v_sign1 number;
12 begin
13 vd_date := pi_workday;
14 vn_loop := pi_count;
15 if pi_count < -1000 or pi_count > 1000 then
16 return to_date('1900-01-01', 'yyyy-mm-dd');
17 end if;
18 loop
19 select count(*) into v_sign from t_holiday where holiday = vd_date;
20 v_sign1 := to_number(to_char(vd_date, 'd'));
21 if v_sign = 0 and v_sign1 <> 1 and v_sign1 <> 7 then
22 exit;
23 end if;
24 vd_date := vd_date+1;
25 end loop;
26 loop
27 exit when vn_loop = 0;
28 if vn_loop>0 then
29 vd_date := vd_date+1;
30 loop
31 select count(*) into v_sign from t_holiday where holiday = vd_da
te;
32 v_sign1 := to_number(to_char(vd_date, 'd'));
33 if v_sign = 0 and v_sign1 <> 1 and v_sign1 <> 7 then
34 exit;
35 end if;
36 vd_date := vd_date+1;
37 end loop;
38 vn_loop := vn_loop-1;
39 else
40 vd_date := vd_date-1;
41 loop
42 select count(*) into v_sign from t_holiday where holiday = vd_da
te;
43 v_sign1 := to_number(to_char(vd_date, 'd'));
44 if v_sign = 0 and v_sign1 <> 1 and v_sign1 <> 7 then
45 exit;
46 end if;
47 vd_date := vd_date-1;
48 end loop;
49 vn_loop :=vn_loop+1;
50 end if;
51 end loop;
52 return vd_date;
53 end;
54 /函数已创建。SQL>
SQL> select f_calcdate(sysdate,2) from dual;F_CALCDATE(SYS
--------------
11-3月 -10 --这里结果是错误的
SQL> create or replace function f_calcdate
2 (
3 pi_workday in date,
4 pi_count in number
5 )
6 return date
7 is
8 vd_date date;
9 vn_loop number;
10 v_sign number;
11 v_sign1 number;
12 begin
13 vd_date := pi_workday;
14 vn_loop := pi_count;
15 if pi_count < -1000 or pi_count > 1000 then
16 return to_date('1900-01-01', 'yyyy-mm-dd');
17 end if;
18 loop
19 select count(*) into v_sign from t_holiday where to_char(holiday,'YY
YY-MM-DD') = to_char(vd_date,'YYYY-MM-DD');
20 v_sign1 := to_number(to_char(vd_date, 'd'));
21 if v_sign = 0 and v_sign1 <> 1 and v_sign1 <> 7 then
22 exit;
23 end if;
24 vd_date := vd_date+1;
25 end loop;
26 loop
27 exit when vn_loop = 0;
28 if vn_loop>0 then
29 vd_date := vd_date+1;
30 loop
31 select count(*) into v_sign from t_holiday where to_char(holiday
,'YYYY-MM-DD') = to_char(vd_date,'YYYY-MM-DD');
32 v_sign1 := to_number(to_char(vd_date, 'd'));
33 if v_sign = 0 and v_sign1 <> 1 and v_sign1 <> 7 then
34 exit;
35 end if;
36 vd_date := vd_date+1;
37 end loop;
38 vn_loop := vn_loop-1;
39 else
40 vd_date := vd_date-1;
41 loop
42 select count(*) into v_sign from t_holiday where to_char(holiday
,'YYYY-MM-DD') = to_char(vd_date,'YYYY-MM-DD');
43 v_sign1 := to_number(to_char(vd_date, 'd'));
44 if v_sign = 0 and v_sign1 <> 1 and v_sign1 <> 7 then
45 exit;
46 end if;
47 vd_date := vd_date-1;
48 end loop;
49 vn_loop :=vn_loop+1;
50 end if;
51 end loop;
52 return vd_date;
53 end;
54 /函数已创建。SQL>
SQL> select f_calcdate(sysdate,2) from dual;F_CALCDATE(SYS
--------------
12-3月 -10
select f_calcdate(trunc(sysdate),2) from dual;