Oracle中几个日期相关的计算
1. 计算当前是第几周
有两种方式:
select to_char(sysdate,'ww') from dual;
--ww的算法为每年1月1日为第一周开始,date+6为每一周结尾
--例如:20050101为第一周的第一天,而第一周的最后一天为20050101+6=20050107
--这里1月1日不一定为周一,月7日也不一定为周日
select to_char(sysdate,'iw') from dual;
--iw的算法为星期一至星期日算一周,且每年的第一个星期一为第一周,
--这种算法,需要关注跨年的那个一周:
--假如跨年的一周,大部分时间属于新年,则上一年的最后几天也算新年的第一周
--比如20130101 是周二,那么2012年的最后几天 都属于2013年的第一周
select to_char(to_date('20130101','yyyymmdd'),'iw') from dual; --01
select to_char(to_date('20121231','yyyymmdd'),'iw') from dual; --01
--假如跨年一周,大部分时间在上年,则跨年周中新年的前几天 属于上年的最后一周
--2020年12月31号是周4,这样跨年的那一周有4天在2020年,所以上面的输出为53
select to_char(to_date('20201231','yyyymmdd'),'iw') from dual; --53
select to_char(to_date('20210101','yyyymmdd'),'iw') from dual; --53
--2021年的前面几天 还是属于 上年的最后一周(53)周
2. 计算上周一 和 上周日的日期
根据中国习惯,一周从周一到周日.
prompt 'week_date_beg_end'
create or replace procedure week_date_beg_end
(
the_date varchar2
)
as
a_date date;
v_i_tmp number(10);
v_tmp_date_beg number(10);
v_tmp_date_end number(10);
begin
a_date := to_date(the_date,'yyyymmdd');
v_i_tmp := to_number(to_char(a_date,'D')); --指定日期的星期,1-7表示周日 - 周六
if v_i_tmp = 1 then -- 表示指定日期是周日
v_i_tmp := 6; -- v_i_tmp 表示指定日期 距离本周一的天数
else
v_i_tmp := v_i_tmp - 2; -- v_i_tmp 表示指定日期 距离本周一的天数
end if;
v_tmp_date_beg := to_number(to_char(a_date - v_i_tmp - 7,'YYYYmmDD')); --指定日期 的 上周一
v_tmp_date_end := to_number(to_char(a_date - v_i_tmp - 1,'YYYYmmDD')); --指定日期 的 上周日
dbms_output.put_line(v_tmp_date_beg);
dbms_output.put_line(v_tmp_date_end);
end;
/
--pl sql developer中测试
set serverout on;
exec week_date_beg_end('20130505');
-- 输出为:
-- 20130422
-- 20130428
-- PL/SQL procedure successfully completed
另,博客 http://blog.csdn.net/limenghua9112/article/details/11193819?reload
中提供的方法不对
-- 这样取的是 在一周内第几天,是以周日为开始的
select to_char(to_date('20130906','yyyymmdd'),'d') from dual;
--结果:6 注释:2013.09.06是周五,为本周的第六天
select to_char(sysdate+(2-to_char(sysdate,'d'))-7,'yyyymmdd') from dual;---上周一
select to_char(sysdate+(2-to_char(sysdate,'d'))-1,'yyyymmdd') from dual;---上周日
--这种算法中,当当前日期为周日时,算出来的上周日还是当天,貌似不对.
--比如,20130505是周日,下面的语句输出的还是 20130505
select to_char(to_date('20130505','yyyymmdd')+(2-to_char(to_date('20130505','yyyymmdd'),'d'))-1,'yyyymmdd') from dual;
3. 计算 上月的第一天 和 最后一天 日期
v_tmp_date_beg := to_number(to_char(last_day(add_months(sysdate,-2)) + 1,'yyyymmdd')); --上月第一天
v_tmp_date_end := to_number(to_char(last_day(add_months(sysdate,- 1)),'yyyymmdd')); --上月最后一天