これまで、前月の初日や末日を算出するくらいしか、PHPを使った日付周りの処理を書いたことがなかったため
問題視することはなかったですが、
DateTimeのsubを利用して、DateIntervalで一月前やそれ以上前の日付を取得すると、
月ごとの日数に関係なく算出されるため、期待通りの結果がとれない。これって、場合によって面倒。
(過去記事漁ればありそうだけど、自分なりのやつを備忘録)
例えば、2018年6月30日の4ヶ月前を、PHPがデフォルトで持っている仕組みで出力すると以下となる。
$operation_date = '2018-06-30';
$diff = 4;
printf('DatetTimeまんまだと→ ');
$date = new DateTime($operation_date);
$date->sub(DateInterval::createFromDateString($diff. ' month'));
var_dump($date->format('Ymd'));
出力結果は、以下。
DatetTimeまんまだと→ string(8) "20180302"
これは嫌だ。
そこで、サンプルコードを作った結果は、以下。
$operation_date = '2018-06-30';
$diff = 4;
$previous = function ($operation_date, $diff=1) {
$date = new DateTime($operation_date);
$diffDate = new DateTime($date->format('Ym01'));
for($i = 0; $i < $diff; $i++) {
$diffDate->sub(DateInterval::createFromDateString('1 month'));
$diffDate = new DateTime($diffDate->format('Ym01'));
}
if ($diffDate->format('t') <= $date->format('d')) {
//end day of month
$date = new DateTime($diffDate->format('Ym'). $diffDate->format('t'));
} else {
//other day of month
$date = new DateTime($diffDate->format('Ym'). $date->format('d'));
}
var_dump($date->format('Ymd'));
};
rintf('カスタマイズだと→ ');
$previous($operation_date, $diff);
カスタマイズだと→ string(8) "20180228"
例外的なこと考える必要はあるかもしれないけど
ひとまず以上。
2018年6月4日 追記: もっとシンプルに書ける → http://jp2.php.net/manual/ja/datetime.add.php#118342