日付計算:指定した月数分を足した日付の計算

軽い気持ちで作り始めたカスタム関数。。。
数分で終わる予定が数時間もかけてしまいました。
しかも、なぜか
「最初の目的とは違う目的」用のカスタム関数を作ってしまいました (TT)
あれば使うので、作ったことはまぁいいんですが、、、

今回作ったのは
「日付に、指定した月数を足した日付を返す」
ことができるカスタム関数です。

どういうことかというと、
「指定日」の日付に「月数」を足して「結果」の日付を返します。

「指定日」2017年7月31日、「月数」1 だったら、
「結果」2017年8月31日 という日付が返ってきます。

月末を指定した場合って面倒。。。
「指定日が月末だった場合、日にちはどうなるのが正解?」
なんて考え始めちゃって…。

A)指定日が月末日だから、結果は「月数を足した月」の月末日にする
B)指定日は月末日だけど、結果は「月数を足した月」の指定日と同じ日にする
どっちがいいのかなぁと。

AとBどっちがいいかはその時々で違いそうな気がしました。
で、結局「タイプ」を指定することで変更できるようにしました。

指定日が月末の日付だった場合、
Aにしたいときはタイプに1を指定→指定日が何日であろうと、月末の日付にする
Bにしたいときはタイプに0を指定→指定日と同じ日付にする
ということにしました。

(B)の場合でやってみたら、
「結果の日付の月」が「指定日の月」より日数が少ない場合は翌月の日付になることもあって、
それはなんだかしっくりこなかったので、この場合は月末日付を返すことにしました。

結局(B)の場合は
B-1)「結果の日付の月」が「指定日の月」より日数が少ない場合は月末日にする
B-2)「結果の日付の月」が「指定日の月」より日数が多い場合は指定日と同じ日にする
の2パターンになりました。

 指定日  月数 タイプ   結果     説明
2017/1/31  1   1   2017/2/28   (A)に該当。月末日になる。
2017/1/31  1   0  2017/2/28   (B−1)に該当。月末日になる。
2017/4/30  1   1   2017/5/31   (A)に該当。月末日になる。
2017/4/30  1   0   2017/5/30  (B−2)に該当。指定日と同じ日付になる。

こんな感じです。
指定日を2月28日にした場合は、

 指定日  月数 タイプ   結果     説明
2017/2/28  1   1   2017/3/31  (A)に該当。月末日になる。
2017/2/28  1   0   2017/3/28  (B−2)に該当。月末日になる。
2017/2/28 -12   1   2016/2/29  (A)に該当。月末日になる。
2017/2/28 -12   0  2016/2/28  (B−2)に該当。指定日と同じ日付になる。。

こんな計算結果が出るようにしました。
・・・わかりづらい。
うまく説明できてませんがなんとかご理解いただけるとうれしいなと。。。

ここにアップするのをためらうほどすっきりしない計算式ではありますが、
『まずは結果が出ればよし』
ということにし、自分用メモとして?アップさせていただきます。

関数名:HN_PlusMonth( TheDate ; PlusNum ; Type )
引数:
TheDate(日付タイプ:この日を基準に計算する)
PlusNum(数字タイプ:ここで指定した数字をTheDateの日付の月に足す)
Type(数字タイプ:0か1を指定する。1=月末日付にする、0=そのままの日付にする)

関数は以下の通り。

/* 目的:[TheDate]に指定した日付の月に、[PlusNum]に指定した数字を足して返す。
    指定した日付が月末日だった場合、
    [Type]が1だったら月末日を、1ではなかったら月末日ではない日付を返す。
関数:HN_PlusMonth( TheDate ; PlusNum ; Type )
-------------------------------------------------------------------------------------------*/
Let ( [
YYYY = Year ( TheDate ) ;
MM = Month( TheDate ) ;
DD = Day ( TheDate ) ;

//指定日が月末日かどうか確認し、月末日でTypeが1だったらLastDateFlgを1にする
NextDate = Date ( MM ; DD + 1 ; YYYY ) ;
NextDateMonth = Month ( NextDate ) ;
LastDateFlg = Case (
        MM = NextDateMonth ; 0 ; //月末日ではない
       Type = 1 ; 1 ; //月末日で、月末日の場合の指示が1(=月末日を返す)
       0 //月末日で、月末日の場合の指示が1ではない(=月末日でなくてもよい)
       );

//指定日に追加月数を足した日付の月が、追加月数を足した月と同じ月になっているか確認し、
//同じだったらSameMonthFlgを1にする

YMD_a = Date ( MM + PlusNum ; DD ; YYYY ) ; //素直に足しただけ
YMD_b = Date ( MM + PlusNum ; 1 ; YYYY ) ; //月を足したときの1日の月数を確認する
MM_a = Month ( YMD_a ) ;
MM_b = Month ( YMD_b ) ;
SameMonthFlg = Case (
         MM_a = MM_b ; 1 ; //月を足した後の日付の月数が1日の月数と同じになってる
         ) ;

YMD_c = Date ( MM + PlusNum + 1 ; 0 ; YYYY ) //月を足した月の月末日

] ;

Case (
IsEmpty ( TheDate ) ; GetAsDate ( "" ) ;
LastDateFlg = 1 ; YMD_c ;
SameMonthFlg = 1 ; YMD_a ;
YMD_c
) //case

) //let

/*----------------------------------------------------------------------------------------
Create Hifumi Nakaoka 2017.06.16*/

多分これで大丈夫だと思う。ちょっと試してみた感じでは…
[PlusNum]にマイナス数を指定すると、
指定月の○ヶ月前が結果として返るはす…です。
試した結果を貼っておきます。


いくらなんでもかけすぎてしまったこの時間、
取り戻すことはできませんが、皆様のお役に立てればうれしいです。
お役に立てるようでしたら、ご自由にお使いくださいませ。

なお、今回も
ご紹介した計算式の使い方、ご質問などはお受けしておりません。
また、ご利用になる場合はご自身の責任でお使いくださいますようお願いいたします<(_ _)>

それと、相変わらず打たれ弱いので、ツッコミなどはこっそりメールでお願いします。

//---追記---//
この記事は、2017年6月に旧ブログに掲載した記事です。
あまり使っていただける機会はないと思っていたのですが、
先ほど「使っていただける」というコメントを頂戴し、
うれしくて転記することにしました。


投稿者