年次有給休暇の付与日を求める際に必要

就業規則等で、年度初めに一斉に付与する会社もあると思いますが(その場合は法令基準を上回る前倒しの付与になっている必要あり)、法定基準通り有給休暇付与を行う場合、入社日の半年後の応当日、そこから1年毎の応当日を求める必要があります。が、月末日付近の扱いで注意が必要です。

6か月後の応当日について求め方を考えてみます。

//PHP 5 >= 5.5.0, PHP 7
$date = '2019-07-14';//入社年月日
$date_6 = six_months_later($date);
echo $date_6;//2020-01-14

function six_months_later($date){
  $date_ob = new DateTimeImmutable($date);
  $re = $date_ob->modify('+6 months')->format('Y-m-d');
  return $re;
}

上記のように、DateTimeオブジェクトを利用すると直感的に「modify(‘+6 months’)で6か月後を求めることができます。
1年のうち大半の日付では、概ねこれで正しい結果が求められます。

しかし、入社年月日が特定の日の場合、意図した結果になりません。

//PHP 5 >= 5.5.0, PHP 7
$date = '2019-05-31';//入社年月日
$date_6 = six_months_later($date);
echo $date_6;//2020-12-01!?

function six_months_later($date){
  $date_ob = new DateTimeImmutable($date);
  $re = $date_ob->modify('+6 months')->format('Y-m-d');
  return $re;
}

5月末日の応当日は、11月末日であるべきですが、12/1になってしまいます。
これは、+6 monthsで求められる日付が、
「5+6月の31日」→「11月31日」→11月は30日が末尾→「11月30+1日」→「12月1日」と求めているせいです。求めている答えとは違いますが、これはこれで正しい挙動をしています。

民法143条では、次のような規定になっています。

民法 第143条 (暦による期間の計算)

1.週、月又は年によって期間を定めたときは、その期間は、暦に従って計算する。
2.週、月又は年の初めから期間を起算しないときは、その期間は、最後の週、月又は年においてその起算日に応当する日の前日に満了する。ただし、月又は年によって期間を定めた場合において、最後の月に応当する日がないときは、その月の末日に満了する。

この規定に従えば、やはり5/31入社の者の有給休暇の付与日は11/30であるべきです。

正しいコード

//PHP 5 >= 5.5.0, PHP 7
$date = '2018-08-31';//入社年月日
$date_6 = six_months_later($date);
echo $date_6;//2019-2-28

function six_months_later($date){
  $date_ob = new DateTime($date);
  $d = $date_ob->format('d');//日を取り出し
  $date_6 = $date_ob->modify('+6 months');
  $date_6_d = $date_6->format('d');//6か月後の日を取り出し
  if($date_6_d!=$d)://異なる日になった
    $date_6 = $date_6->modify('last day of last month');
  endif;

  $re = $date_6->format('Y-m-d');
  return $re;
}

上記では、入社年月日の「日」を取り出し、modify(‘+6 months’)で生成した日付の「日」と比較をしています。これが一致しないということは、先ほどの例のように翌月の月初に食い込みが発生しているので、modify(‘last day of last month’)で、前月の末日を取得すれば、意図した結果が導き出せます。
「前月末日」なので、8月29~31日の入社の場合、半年後の2月が閏年により29日まである場合には2/29、平年であれば2/28がきちんと返ってきます。

「入社日の半年後の応当日」はこれで解決ですが・・・「〇ヶ月後の応当日」とかって日付関連では割とよく使うので、DateTimeImmutableクラス/DateTimeクラスの標準で上手い事対応してくれないかな。。

注意点

上記は各コードの文頭にも記述しましたが、DateTimeImmutableクラスを利用している場合は、PHP5では5.5以降、もしくはPHP7でなければ動作しません。
PHP5.2~5.4までの場合、これの代わりにDateTimeクラスが利用できます。
当記事で紹介したコードの場合、DateTimeImmutableをDateTimeにただ書き換えただけでも問題なく動作します。
DateTimeとDateTimeImmutableの違いについては下記。

https://qiita.com/juve_534/items/b450dc4072bb5539582a