我写了一个,算法有点复杂:select to_date('2005-01-01','yyyy-mm-dd') 
       +mod(7 - to_number(to_char(to_date('2005-01-01','yyyy-mm-dd'),'d')) + i,7)
       + (n - 1)*7 as bngdate,
       to_date('2005-01-01','yyyy-mm-dd') 
       +mod(7 - to_number(to_char(to_date('2005-01-01','yyyy-mm-dd'),'d')) + i,7)
       + n*7-1 as enddate
from dual;上式中有两个参数,n和i,n为第n个完整周,i为每星期起始日,i=1表示从星期日开始算一周的第一天,i=2表示从星期一开始算一周的第一天,依次类推....。
将2005换成其它年份,就可以算其它年份的。可以改成过程或函数。示例:SQL> select to_date('2005-01-01','yyyy-mm-dd')
  2         +mod(7 - to_number(to_char(to_date('2005-01-01','yyyy-mm-dd'),'d')) + 2,7)
  3         + (38 - 1)*7 as bngdate,
  4         to_date('2005-01-01','yyyy-mm-dd')
  5         +mod(7 - to_number(to_char(to_date('2005-01-01','yyyy-mm-dd'),'d')) + 2,7)
  6         + 38*7-1 as enddate
  7  from dual;BNGDATE     ENDDATE
----------- -----------
2005-9-19   2005-9-25各位有什么更好的算法,或者知道有直接函数的话,希望能贡献出来。

解决方案 »

  1.   

    create or replace type monthdaytype is varray(12) of integer;
    create or replace procedure GetWeekDay(
      v_year number,
      num number,
      begdate out date,
      endate out date
    ) is
      monthday monthdaytype;
      n integer:=1;
      j integer;
      daynum integer;
    begin
      if v_year < -4712 or v_year > 4712 then
        raise_application_error(-1000,'wrong year');
      end if;
      if num < 1 or num > 52 then
        raise_application_error(-2000,'wrong week number');
      end if;
      if (v_year mod 400)=0 or ((v_year mod 4)=0 and (v_year mod 100)<>0) then 
        monthday:=monthdaytype(31,29,31,30,31,30,31,31,30,31,30,31);
      else
        monthday:=monthdaytype(31,28,31,30,31,30,31,31,30,31,30,31);
      end if;
      daynum:=monthday(1);
      j:=7*(num-1)+1;
      while 7*(num-1)+1>daynum loop
        j:=7*(num-1)+1-monthday(n);
        n:=n+1;
        daynum:=daynum+monthday(n);
      end loop;
      begdate:=to_date(to_char(v_year)||lpad(n,2,0)||lpad(j,2,0),'yyyy-mm-dd');
      if j+6>monthday(n) then
        j:=(j+6) mod monthday(n);
        n:=n+1;
      else
        j:=j+6;
      end if;
      endate:=to_date(to_char(v_year)||lpad(n,2,0)||lpad(j,2,0),'yyyy-mm-dd');  
    end GetWeekDay;