PHPerからしたらありふれすぎた話だけど、2021/07/31の1ヶ月前をCarbonで取得しようとして死んだ。
なにがおきたか
こうすると
$date = new Carbon('20210731')->subMonth(1); echo($date);
こうなる
2021-07-01 00:00:00
2021-06-30 00:00:00じゃないの?
なぜか
CarbonはDateTimeのラッパー
7/31から1ヶ月減算すると6/31になるが、6/31という日付は存在しない。
なので、6月の月末日の6/30と6/31の差分を計算し、6/30に日付を1日加算する。
結果として7/1になる。
という仕様らしい。
解決策
subMonthsNoOverflow
を使う
$date = new Carbon('20210731'); echo($date->subMonthsNoOverflow(1));
2021-06-30 00:00:00
$date = new Carbon('20210731123005'); echo($date->subMonthsNoOverflow(1));
2021-06-30 12:30:05
補足
翌月版もある
$date = new Carbon('20210831123005'); echo($date->addMonthsNoOverflow(1));
2021-09-30 12:30:05
9/31は存在しないがオーバーフローさせずに9/30日になっている