由於end_date
沒有小數秒,或任何時間組件,您可以使用add_months
,並轉換爲timestamp
:
select cast(add_months(end_date, 2) as timestamp) from ...
但add_months
都有自己的怪癖。如果原始日期是月份的最後一天,則會得到調整後的月份的最後一天 - 如果在這種情況下要更短的月份,這就是您想要的,但如果您要去另一種方式:
with t as (
select to_timestamp('2013-07-31', 'YYYY-MM-DD') as end_date from dual
union all select to_timestamp('2013-06-30', 'YYYY-MM-DD') from dual
union all select to_timestamp('2013-02-28', 'YYYY-MM-DD') from dual
union all select to_timestamp('2012-02-29', 'YYYY-MM-DD') from dual
)
select end_date, cast(add_months(end_date, 2) as timestamp)
from t;
END_DATE CAST(ADD_MONTHS(END_DATE,2)AST
------------------------------ ------------------------------
2013-07-31 00:00:00.000000 2013-09-30 00:00:00.000000
2013-06-30 00:00:00.000000 2013-08-31 00:00:00.000000
2013-02-28 00:00:00.000000 2013-04-30 00:00:00.000000
2012-02-29 00:00:00.000000 2012-04-30 00:00:00.000000
或者你可以創建自己的函數來處理劣棗,向後調整,直到它找到一個有效的:
create or replace function adjust_timestamp(orig_ts in timestamp,
months in number)
return timestamp is
new_ts timestamp;
offset number := 0;
bad_adjustment exception;
pragma exception_init(bad_adjustment, -01839);
begin
while new_ts is null loop
begin
new_ts := orig_ts - numtodsinterval(offset, 'DAY')
+ numtoyminterval(months, 'MONTH');
exception
when bad_adjustment then
offset := offset + 1;
continue;
end;
end loop;
return new_ts;
end;
/
它使用了ORA-定義異常01839錯誤代碼來捕獲不良的日期,並且它在循環中執行,因此它可以向後工作(通過offset
),直到找到一個沒有錯誤的代碼。
with t as (
select to_timestamp('2013-07-31', 'YYYY-MM-DD') as end_date from dual
union all select to_timestamp('2013-06-30', 'YYYY-MM-DD') from dual
union all select to_timestamp('2013-02-28', 'YYYY-MM-DD') from dual
union all select to_timestamp('2012-02-29', 'YYYY-MM-DD') from dual
)
select end_date, adjust_timestamp(end_date, 2)
from t;
END_DATE ADJUST_TIMESTAMP(END_DATE,2)
------------------------------ ------------------------------
2013-07-31 00:00:00.000000 2013-09-30 00:00:00.000000
2013-06-30 00:00:00.000000 2013-08-30 00:00:00.000000
2013-02-28 00:00:00.000000 2013-04-28 00:00:00.000000
2012-02-29 00:00:00.000000 2012-04-29 00:00:00.000000
這給add_months
版本提供了不同的結果。你需要確定你得到了什麼,以及你希望數據的行爲。
:你結束日期是否包含時間戳? –
'end_date'是否有小數秒?如果是月末,你是否總想調整日期;那麼2013-02-28之後的2個月會是2013-04-28還是2013-04-30?事實上,這是否總是一個月的最後一天? –
@GauravSoni是的,END_DATE是時間戳值。 –