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')); --上月最後一天