2021-05-17
から 2021-05-21
を1日ずつループしたい
そんなときに便利(?)な DatePeriod というクラスがあります
DatePeriod
は Traversable
を実装しているのでオブジェクトのまま foreach
でループできます
(ここだけは)素敵ですね!
しかし、なにも考えずに使うとはまってしまうので注意が必要です!
まずはコード
// 開始日
$startDateTime = new DateTime('2021-05-17');
// 終了日
$endDateTime = new DateTime('2021-05-21');
// 間隔(1日)
// 最初の文字は P 固定(これいる?)
// 1D は 1日
$interval = new DateInterval('P1D');
$period = new DatePeriod($startDateTime, $interval, $endDateTime);
foreach ($period as $date) {
echo $date->format('Y-m-d'), PHP_EOL;
}
結果を見てみると 2021-05-21
が含まれていません
2021-05-17
2021-05-18
2021-05-19
2021-05-20
原因
DatePeriod
は時分秒マイクロ秒まで見て 未満 で比較します
なので最後の日付が含まれません
解決方法
最後の日付を1秒ほど、ずらしてあげましょう
// 開始日
$startDateTime = new DateTime('2021-05-17');
// 終了日
- $endDateTime = new DateTime('2021-05-21');
+ $endDateTime = (new DateTime('2021-05-21'))->setTime(0, 0, 1); // 0時0分1秒にする
// 間隔(1日)
// 最初の文字は P 固定(これいる?)
// 1D は 1日
$interval = new DateInterval('P1D');
$period = new DatePeriod($startDateTime, $interval, $endDateTime);
foreach ($period as $date) {
echo $date->format('Y-m-d'), PHP_EOL;
}
2021-05-21
もでました!
2021-05-17
2021-05-18
2021-05-19
2021-05-20
2021-05-21
おまけ
Carbon は(本当に)便利です
use Carbon\CarbonPeriod;
$period = CarbonPeriod::start('2021-05-17')->days(1)->end('2021-05-21');
foreach ($period as $date) {
echo $date->format('Y-m-d'), PHP_EOL;
}
逆に最後の日付を含まないようにするには end
の第2引数 $inclusive
に false
を渡してあげればOK
Carbon使おう!