1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

2021-05-17 から 2021-05-21 を1日ずつループしたい
そんなときに便利(?)な DatePeriod というクラスがあります

DatePeriodTraversable を実装しているのでオブジェクトのまま 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引数 $inclusivefalse を渡してあげればOK

Carbon使おう!

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?