--这几天坛子里有些人在问一些日期的问题, --类似: -- 求一年中某一个周的第一天和最后一天 -- 求上个月的第一个周日和最后一个周日 --现将这些总结一下,忘大家指点,共同学习 --需求一: -- 我给一个周数 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.html SELECT 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