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って呼ぶべきでは。長いからかな。