PHPで日付処理を行うのに便利なCarbonですが、いくつか注意した点があるので共有。
1.加減算処理は元の変数に結果が入る。
(※これはハマらない人の方が多いかも・・。)
例:2019/05/01から、5日後と10日後の日をそれぞれ算出する
間違ったプログラム
$dt = Carbon::parse('2019/05/01');
// 5日後
$after_5_day = $dt->addDay(5); // <- この処理で$dtが、2019/05/06になる。
echo($after_5_day->format('Y/m/d'). "\n");
// 10日後
$after_10_day = $dt->addDay(10); <- 2019/05/06の10日後になる。
echo($after_10_day->format('Y/m/d'). "\n");
結果
2019/05/06
2019/05/16
正解プログラム
$dt = Carbon::parse('2019/05/01');
// 5日後
$after_5_day = $dt->addDay(5);
echo($after_5_day->format('Y/m/d'). "\n");
$dt2 = Carbon::parse('2019/05/01'); // <- 基準日を再定義する。
// 10日後
$after_10_day = $dt2->addDay(10);
echo($after_10_day->format('Y/m/d'). "\n");
結果
2019/05/06
2019/05/11
2.Xヶ月後は、addMonthではなく、addMonthsNoOverflowを使う。
例:2019/01/01から1ヶ月後の2019/02/01を出したい
$dt = Carbon::parse('2019/01/01')->addMonth(1);
echo($dt->format('Y/m/d'). "\n");
結果
2019/02/01
この場合は、addMonthでOK。
例:2019/01/31から1ヶ月後の2019/02/28を出したい
1月末日から、2月末日を算出する時
$dt = Carbon::parse('2019/01/31')->addMonth(1);
echo($dt->format('Y/m/d'). "\n");
結果
2019/03/03
addMonthだと、2019/02/29〜31までの値がないので、31日と28の差分で03/03となる。
上記の場合は、addMonthsNoOverflowを使う。
$dt = Carbon::parse('2019/01/31')->addMonthsNoOverflow(1);
echo($dt->format('Y/m/d'). "\n");
結果
2019/02/28
subMonthも同様に、subMonthsNoOverflowを使う。
3.日数の差分は、dと、daysを使い分ける。
例:2019/04/05と、2019/05/10の差分を算出
$diff = Carbon::parse('2019/04/05')->diff(Carbon::parse('2019/05/10'));
echo($diff->d. "\n"); // 日数のみの差分
echo($diff->days. "\n"); // 年月を含めた差分
結果
5
35