--这几天坛子里有些人在问一些日期的问题,
--类似:
--    求一年中某一个周的第一天和最后一天
--    求上个月的第一个周日和最后一个周日
--现将这些总结一下,忘大家指点,共同学习--需求一:
--     我给一个周数 32 返回这周的第一天 和最后一天
--此问题的讨论可参考:http://topic.csdn.net/u/20101118/13/dd78c0cc-3ea3-42ac-a2f8-674840146ab1.html--这里我做了一个每周对应的第一天和最后一天的临时表
--关键在于当年第一周的第一天和最后一天怎么算,后面只需加上7天就是一周,类推
--还有就是确定的是,一年总共只有53周
--Oracle中周日为第一天 ,周六为最后一天
SELECT LEVEL 周次,
    (Trunc(SYSDATE,'yyyy')-To_Char(Trunc(SYSDATE,'yyyy'),'d')+1)+(LEVEL-1)*7  当周第一天,
    (Trunc(SYSDATE,'yyyy')+(7-To_Char(Trunc(SYSDATE,'yyyy'),'d')))+(LEVEL-1)*7 当周最后一天
FROM dual
CONNECT BY LEVEL<=53--特别提醒:
--这里主要是对于当年第一周的第一天和最后一周的最后一天,可能存在跨年份的情况 ,从上面的结果中可以看出
--根据具体实际需求再来做更改,这里我不再修改
-- 需求二:
--        求上个月的第一个周日和最后一个周日
--此问题的讨论可参考:http://topic.csdn.net/u/20101118/20/5d20b0bf-2ad5-4e69-9706-42a251d51235.htmlSELECT
      CASE WHEN To_Char(trunc(add_months(sysdate,-1),'mm'),'d')=1 --判断第一天是否是周日
                THEN trunc(add_months(sysdate,-1),'mm')
           ELSE
                trunc(add_months(sysdate,-1),'mm')+(7-to_char(trunc(add_months(sysdate,-1),'mm'),'d'))+1
      END first_sunday,
      CASE WHEN To_Char(last_day(add_months(sysdate,-1)),'d')=1 --判断最后一天是否是周日
                THEN last_day(add_months(sysdate,-1))
           ELSE --这里可以不需要再判断最后一个周日跨月情况
                last_day(add_months(sysdate,-1))-to_char(last_day(add_months(sysdate,-1)),'d')+1
      END last_first_sunday
FROM dual;
-- 这里我做的是,产生当年每个月的第一个周日和最后一个周日的临时表
SELECT
      current_month,
      CASE WHEN To_Char(firstday,'d')=1 --判断第一天是否是周日
                THEN firstday
           ELSE
                firstday + (7-to_char(firstday,'d')) + 1  --不需要判断第一个周日是否跨月
      END first_sunday,
      CASE WHEN To_Char(lastday,'d')=1 --判断最后一天是否是周日
                THEN lastday
           ELSE
                lastday - to_char(lastday,'d')+1  --这里也不需要判断最后一个周日是否跨月份
      END last_sunday
FROM(
--生成每个月的第一天和最后一天
SELECT level current_month,
       Trunc(Add_Months(Trunc(SYSDATE,'yyyy'),level-1),'mm') firstday,
       Last_Day(Add_Months(Trunc(SYSDATE,'yyyy'),level-1)) lastday
FROM dual
CONNECT BY LEVEL<=12
)--补充两个需求:
--需求三:查找2010-05-05至2010-04-01间除星期一和七的天数 ,   
      select count(*)      
      from ( select rownum rnum      
             from all_objects      
             where rownum <= to_date('2010-05-05','yyyy-mm-dd') - to_date('2010-04-01','yyyy-mm-dd')+1
           )      
      where to_char( to_date('2010-04-01','yyyy-mm-dd')+rnum-1, 'D' ) not in ( '1', '7' ) ;     
 
 --  PL/SQL实现:
    declare 
      n number;
      temp varchar2(1);
      day number:=0;
    begin  
      select to_date('2010-05-05','yyyy-mm-dd') - to_date('2010-04-01','yyyy-mm-dd')+1 into n from dual;
      dbms_output.put_line('between 2010-05-05 and 2010-04-01 have '||n|| ' days!');
      for i in 1..n loop
        select to_char(to_date('2010-04-01','yyyy-mm-dd')+i,'d') into temp from dual;
        if(temp!='1' and temp!='7') then
           day:=day+1;
        end if;
      end loop;
      dbms_output.put_line('except 1 and 7 ,else have '||day||' days!');
    end;
-- 需求四:.
-- 1)当前月份的每周五的日期(如:当前时间是2010年05月)
--   方法一:
    select to_char(t.d,'YY-MM-DD') from (
  select trunc(sysdate, 'MM')+rownum-1 as d
  from all_objects  --返回当前月的每一天的日期!因为all_objects中的数据比较多,一定>31! 
  where rownum < 32) t
  where to_char(t.d, 'MM') = to_char(sysdate, 'MM') --找出当前月份的周五的日期
  and trim(to_char(t.d, 'Day')) = '星期五'--   方法二:
    select next_day(trunc(sysdate,'mm')-1,6)+(rownum-1)*7
    from dual
    connect by rownum<=(add_months(trunc(sysdate,'mm'),1)-next_day(trunc(sysdate,'mm')-1,6))/7--  2)当前日期的前三个月中的每周五的日期
   select next_day(trunc(add_months(sysdate,-3),'mm')-1,6)+(rownum-1)*7
   from dual
   connect by rownum<=(sysdate-next_day(trunc(add_months(sysdate,-3),'mm')-1,6))/7