twitter で見かけたのでちょっと考えてみる。
SQL Server
select dateadd(month, 1, cast('2016/02/29' as date))
Oracle
select add_months('2016/02/29', 1) from dual
足す前の日付と足した後の日付の 日 の部分が違った場合で、足した後の方が大きい時だけ問題になるで良いのかな。
- 日が同じ => 問題無し
- 日が違って、足した時の方が小さい => 足す前の 日 が足した後の月に存在しない 例:1/30 に 1ヶ月足したら 2/28 or 2/29 になるパターン
- 日が違って、足した時の方が大きい => 足す前が月末日、足す前の月の日数が足した後の月の日数より少ない。例:4/30 に 1ヶ月足したら 5/31
最後のパターンだけ差し替えるとこんな感じ。*1
create or replace function ADD_MONTHS_SQLSERVER(target date, plus number) return date
is
result date;
begin
select add_months(target, plus) into result from dual;
select
case
when to_char(result, 'DD') > to_char(target, 'DD')
then to_date(to_char(result, 'YYYYMM') || to_char(target, 'DD'), 'YYYYMMDD')
else result
end into result
from dual;
return result;
end;
function 作るのいやだったらこんな感じ?
select
case when to_char(add_months(sysdate, 2), 'DD') > to_char(sysdate, 'DD')
then to_date(to_char(add_months(sysdate, 2), 'YYYYMM') || to_char(sysdate, 'DD'), 'YYYYMMDD')
else add_months(sysdate, 2)
end as add_months_sqlserver
from dual
LAST_DAY とか使うかなーと思ったけど、そうでもなかった。
※雰囲気動くとこまでしか確認してないから利用は自己責任で!