24
31

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 5 years have passed since last update.

PHPで日付をループする方法と罠

Last updated at Posted at 2016-11-06

PHP の DatePeriod で日付をループする。
見慣れないし存在自体忘れそう&地味に面倒くさい仕様なのでメモ。

使い方

ループする期間の始点、終点(?)、間隔を指定する。

<?php
$start    = new DateTime('2016-11-02'); // 16/11/02 から
$end      = new DateTime('2016-11-08'); // 16/11/08 まで
$interval = new DateInterval('P2D');    // 2日間隔で(最初に P)

$period = new DatePeriod($start, $interval, $end); // 順番注意

foreach ($period as $date) {
    echo $date->format('Y-m-d');
    echo "\n";
}

// 出力(16/11/08 は出てこない)
/*
2016-11-02
2016-11-04
2016-11-06
*/

終点はループに含まれないので注意。わかりづら。

終点の日付も含める

DatePeriod という名前だけど突っ込んでるのもループしてるのも DateTime オブジェクトなので、時刻も見てる&持ってる。

終点の日付も含めたいなら、終点の時刻を始点より後に設定しちゃえばいい。

<?php
$start    = new DateTime('2016-11-02');          // 16/11/02 00:00:00
$end      = new DateTime('2016-11-08 00:00:01'); // 16/11/08 00:00:01
$interval = new DateInterval('P2D');

$period = new DatePeriod($start, $interval, $end);

foreach ($period as $datetime) {
    echo $datetime->format('Y-m-d H:m:s');
    echo "\n";
}

// 出力(16/11/08 も出てくる)
/*
2016-11-02 00:00:00
2016-11-04 00:00:00
2016-11-06 00:00:00
2016-11-08 00:00:00
*/

考えるの面倒くさいし始点には00:00:00、終点には23:59:59とでもつけちゃうのがいいとおもう。

ちなみに、既にある DateTime オブジェクトの時刻を書き換えるのはsetTime()

<?php
$today = new DateTime(null, new DateTimeZone('Asia/Tokyo')); // 2016-11-07 01:17:38
$today->setTime(12, 34, 56); // 2016-11-07 12:34:56

破壊的操作。

(11/13 追記)終点を表示させたい日の翌日にする

コメントにてアドバイスを頂いたので追記。
こちらでも思った通りの表示ができます。(詳しくはコメントのほうを)

$end = new DateTime('2016-11-09'); // 16/11/08 まで表示され、16/11/09 は表示されない。

ちなみに 1日後にするのはこう。(筆者による)
出たな DateInterval……!

$end = new DateTime('2016-11-08');
$end->add(new DateInterval('P1D')); // 16/11/09

時刻をループする(脱線)

ちなみに時刻でもループできる。

<?php
$start    = new DateTime('2016-11-02 22:33:44');
$end      = new DateTime('2016-11-08');
$interval = new DateInterval('P1DT2H3M45S'); // 1日と2時間3分45秒間隔で

$period = new DatePeriod($start, $interval, $end);

foreach ($period as $datetime) {
    echo $datetime->format('Y-m-d H:i:s');
    echo "\n";
}

// 出力
/*
2016-11-02 22:33:44
2016-11-04 00:37:29
2016-11-05 02:41:14
2016-11-06 04:44:59
2016-11-07 06:48:44
*/

DateInterval って他にどこで使うか知らないけどどうして最初にPつけるんだろう……。
単位は下表のとおり。複数並べるときは表中で上にあるものから。

単位 記号
Y
M
D
時間 H
M
S

まさかのMかぶってるっていう。
そのせいか時刻の前にはTをつけることになってる。
'P3M'だと3ヶ月、'PT3Mだと3分。ウケる。

例えば「1日と2時間」のつもりで'P1D2M'と書くと Fatal error 吐かれる。
正しくは'P1DT2M'。ウケる。

ていうかこれ DateTimeInterval, DateTimePeriodって呼ぶべきでは。長いからかな。

24
31
4

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
24
31

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?