本篇是接续前一篇,因有朋友(allenc)要计算oracle的周数日期起迄,
所以测试了一下,
测试结果如下:
-- 特殊周数计算
-- 星期日到星期六为一周(与ww及iw算法不同)
-- 例2005年的第一周起迄是同一天,是20050101
-- 例2004年的第一周起为20040101迄为20040103
-- 计算第一周的天数
create or replace function fdf(p_date in date) return number
is
begin
-- 检查是否传入要计算那一年的一月一日
if to_char(to_char(p_date,‘ddd‘)) <> ‘001‘ then
return null;
end if;
--如果第一周的第一天刚好也是最后一天时,传回1
if to_char(p_date,‘d‘) <> ‘7‘ then
return (next_day(p_date,‘SATURDAY‘) - p_date +1);
else
return 1;
end if;
exception
when others then
dbms_output.put_line(sqlerrm);
end;
计算公式:
起 :decode(周,1,计算当年的一月一日,计算当年的一月一日 + (fdf(计算当年的一月一日) + (周 - 2)*7)) as 起
迄(第一种算法):decode(周,53,to_date(to_char(计算当年的一月一日,‘yyyy‘)||‘12‘||‘31‘,‘yyyymmdd‘),计算当年的一月一日 + (fdf(计算当年的一月一日) + (周-1)*7-1)) as 迄
迄(第二种算法):decode(周,53,last_day(trunc(计算当年的一月一日,‘mm‘)+340),计算当年的一月一日 + (fdf(计算当年的一月一日) + (周-1)*7-1)) as 迄
上面的参数部份,"计算当年的一月一日"为date type,"周"为number type
传回值一律是date型态
例如:
--2004年第1周
select decode(1,1,to_date(‘20040101‘,‘yyyymmdd‘),to_date(‘20040101‘,‘yyyymmdd‘) + (fdf(to_date(‘20040101‘,‘yyyymmdd‘)) + (1 - 2)*7)) as s_week,decode(1,53,to_date(to_char(to_date(‘20040101‘,‘yyyymmdd‘),‘yyyy‘)||‘12‘||‘31‘,‘yyyymmdd‘),to_date(‘20040101‘,‘yyyymmdd‘) + (fdf(to_date(‘20040101‘,‘yyyymmdd‘)) + (1-1)*7-1)) as e_week from dual;
--2004年第3周
select decode(3,1,to_date(‘20040101‘,‘yyyymmdd‘),to_date(‘20040101‘,‘yyyymmdd‘) + (fdf(to_date(‘20040101‘,‘yyyymmdd‘)) + (3 - 2)*7)) as s_week,decode(3,53,to_date(to_char(to_date(‘20040101‘,‘yyyymmdd‘),‘yyyy‘)||‘12‘||‘31‘,‘yyyymmdd‘),to_date(‘20040101‘,‘yyyymmdd‘) + (fdf(to_date(‘20040101‘,‘yyyymmdd‘)) + (3-1)*7-1)) as e_week from dual;
--2004年第53周
select decode(53,1,to_date(‘20040101‘,‘yyyymmdd‘),to_date(‘20040101‘,‘yyyymmdd‘) + (fdf(to_date(‘20040101‘,‘yyyymmdd‘)) + (53 - 2)*7)) as s_week,decode(53,53,to_date(to_char(to_date(‘20040101‘,‘yyyymmdd‘),‘yyyy‘)||‘12‘||‘31‘,‘yyyymmdd‘),to_date(‘20040101‘,‘yyyymmdd‘) + (fdf(to_date(‘20040101‘,‘yyyymmdd‘)) + (53-1)*7-1)) as e_week from dual;
--2005年第1周
select decode(1,1,to_date(‘20050101‘,‘yyyymmdd‘),to_date(‘20050101‘,‘yyyymmdd‘) + (fdf(to_date(‘20050101‘,‘yyyymmdd‘)) + (1 - 2)*7)) as s_week,decode(1,53,to_date(to_char(to_date(‘20050101‘,‘yyyymmdd‘),‘yyyy‘)||‘12‘||‘31‘,‘yyyymmdd‘),to_date(‘20050101‘,‘yyyymmdd‘) + (fdf(to_date(‘20050101‘,‘yyyymmdd‘)) + (1-1)*7-1)) as e_week from dual;
--2005年第3周
select decode(3,1,to_date(‘20050101‘,‘yyyymmdd‘),to_date(‘20050101‘,‘yyyymmdd‘) + (fdf(to_date(‘20050101‘,‘yyyymmdd‘)) + (3 - 2)*7)) as s_week,decode(3,53,to_date(to_char(to_date(‘20050101‘,‘yyyymmdd‘),‘yyyy‘)||‘12‘||‘31‘,‘yyyymmdd‘),to_date(‘20050101‘,‘yyyymmdd‘) + (fdf(to_date(‘20050101‘,‘yyyymmdd‘)) + (3-1)*7-1)) as e_week from dual;
--2005年第53周
select decode(53,1,to_date(‘20050101‘,‘yyyymmdd‘),to_date(‘20050101‘,‘yyyymmdd‘) + (fdf(to_date(‘20050101‘,‘yyyymmdd‘)) + (53 - 2)*7)) as s_week,decode(53,53,to_date(to_char(to_date(‘20050101‘,‘yyyymmdd‘),‘yyyy‘)||‘12‘||‘31‘,‘yyyymmdd‘),to_date(‘20050101‘,‘yyyymmdd‘) + (fdf(to_date(‘20050101‘,‘yyyymmdd‘)) + (53-1)*7-1)) as e_week from dual;
--2005年第53周方法2
select decode(53,1,to_date(‘20050101‘,‘yyyymmdd‘),to_date(‘20050101‘,‘yyyymmdd‘) + (fdf(to_date(‘20050101‘,‘yyyymmdd‘)) + (53 - 2)*7)) as s_week,decode(53,53,last_day(trunc(to_date(‘20050101‘,‘yyyymmdd‘),‘mm‘)+340),to_date(‘20050101‘,‘yyyymmdd‘) + (fdf(to_date(‘20050101‘,‘yyyymmdd‘)) + (53-1)*7-1)) as e_week from dual;
结果如下:
127.0.0.1:asdb:WF>--2004年第1周
127.0.0.1:asdb:WF>select decode(1,1,to_date(‘20040101‘,‘yyyymmdd‘),to_date(‘20040101‘,‘yyyymmdd‘) + (fdf(to_date(‘20040101‘,‘yyyymmdd‘)) + (1 - 2)*7)) as s_week,decode(1,53,to_date(to_char(to_date(‘20040101‘,‘yyyymmdd‘),‘yyyy‘)||‘12‘||‘31‘,‘yyyymmdd‘),to_date(‘20040101‘,‘yyyymmdd‘) + (fdf(to_date(‘20040101‘,‘yyyymmdd‘)) + (1-1)*7-1)) as e_week from dual;
S_WEEK E_WEEK
--------- ---------
01-JAN-04 03-JAN-04
Elapsed: 00:00:00.00
127.0.0.1:asdb:WF>--2004年第3周
127.0.0.1:asdb:WF>select decode(3,1,to_date(‘20040101‘,‘yyyymmdd‘),to_date(‘20040101‘,‘yyyymmdd‘) + (fdf(to_date(‘20040101‘,‘yyyymmdd‘)) + (3 - 2)*7)) as s_week,decode(3,53,to_date(to_char(to_date(‘20040101‘,‘yyyymmdd‘),‘yyyy‘)||‘12‘||‘31‘,‘yyyymmdd‘),to_date(‘20040101‘,‘yyyymmdd‘) + (fdf(to_date(‘20040101‘,‘yyyymmdd‘)) + (3-1)*7-1)) as e_week from dual;
S_WEEK E_WEEK
--------- ---------
11-JAN-04 17-JAN-04
Elapsed: 00:00:00.00
127.0.0.1:asdb:WF>--2004年第53周
127.0.0.1:asdb:WF>select decode(53,1,to_date(‘20040101‘,‘yyyymmdd‘),to_date(‘20040101‘,‘yyyymmdd‘) + (fdf(to_date(‘20040101‘,‘yyyymmdd‘)) + (53 - 2)*7)) as s_week,decode(53,53,to_date(to_char(to_date(‘20040101‘,‘yyyymmdd‘),‘yyyy‘)||‘12‘||‘31‘,‘yyyymmdd‘),to_date(‘20040101‘,‘yyyymmdd‘) + (fdf(to_date(‘20040101‘,‘yyyymmdd‘)) + (53-1)*7-1)) as e_week from dual;
S_WEEK E_WEEK
--------- ---------
26-DEC-04 31-DEC-04
Elapsed: 00:00:00.01
127.0.0.1:asdb:WF>
127.0.0.1:asdb:WF>--2005年第1周
127.0.0.1:asdb:WF>select decode(1,1,to_date(‘20050101‘,‘yyyymmdd‘),to_date(‘20050101‘,‘yyyymmdd‘) + (fdf(to_date(‘20050101‘,‘yyyymmdd‘)) + (1 - 2)*7)) as s_week,decode(1,53,to_date(to_char(to_date(‘20050101‘,‘yyyymmdd‘),‘yyyy‘)||‘12‘||‘31‘,‘yyyymmdd‘),to_date(‘20050101‘,‘yyyymmdd‘) + (fdf(to_date(‘20050101‘,‘yyyymmdd‘)) + (1-1)*7-1)) as e_week from dual;
S_WEEK E_WEEK
--------- ---------
01-JAN-05 01-JAN-05
Elapsed: 00:00:00.00
127.0.0.1:asdb:WF>--2005年第3周
127.0.0.1:asdb:WF>select decode(3,1,to_date(‘20050101‘,‘yyyymmdd‘),to_date(‘20050101‘,‘yyyymmdd‘) + (fdf(to_date(‘20050101‘,‘yyyymmdd‘)) + (3 - 2)*7)) as s_week,decode(3,53,to_date(to_char(to_date(‘20050101‘,‘yyyymmdd‘),‘yyyy‘)||‘12‘||‘31‘,‘yyyymmdd‘),to_date(‘20050101‘,‘yyyymmdd‘) + (fdf(to_date(‘20050101‘,‘yyyymmdd‘)) + (3-1)*7-1)) as e_week from dual;
S_WEEK E_WEEK
--------- ---------
09-JAN-05 15-JAN-05
Elapsed: 00:00:00.00
127.0.0.1:asdb:WF>--2005年第53周
127.0.0.1:asdb:WF>select decode(53,1,to_date(‘20050101‘,‘yyyymmdd‘),to_date(‘20050101‘,‘yyyymmdd‘) + (fdf(to_date(‘20050101‘,‘yyyymmdd‘)) + (53 - 2)*7)) as s_week,decode(53,53,to_date(to_char(to_date(‘20050101‘,‘yyyymmdd‘),‘yyyy‘)||‘12‘||‘31‘,‘yyyymmdd‘),to_date(‘20050101‘,‘yyyymmdd‘) + (fdf(to_date(‘20050101‘,‘yyyymmdd‘)) + (53-1)*7-1)) as e_week from dual;
S_WEEK E_WEEK
--------- ---------
25-DEC-05 31-DEC-05
Elapsed: 00:00:00.01
127.0.0.1:asdb:WF>