まとめ
- 基本的にはDateTimeImmutableを使え
- DatePeriodで事足りる場合は多い。
DateTimeを使わない例
$todayとか$tomorrowとかには使わない(DateTimeImmutableを使え)
例えば、知らずに以下のようなコードを書くと、ハマります。
<?php
// 例えば、2016-06-15 15:48
$tomorrow = new DateTime();
// ここで、2016-06-16 15:48になる。
$tomorrow->add(new DatetimeInterval('P1D'));
// どこか知らな場所でこういうことをやると…
$dayAfterTomorrow = $tomorrow->add(new DatetimeInterval('P1D'));
// $tomorrow 変数が、tomorrowじゃなくなった!!!!
普通、「今日」とか「明後日」とか「9日後」などといった、特定の日付を表す変数 には、DateTimeImmutableを使います。
一方向(Unidirectional)のカーソルには使わない(DatePeriodで事足りる)
<?php
function getGenerator(DateTime $first, DateTime $last){
$cursor = $first;
while($first <= $last) {
yield $cursor;
$first->add(new DateTimeInterval('P1D'));
}
}
$today = new DateTimeImmutable();
$nextFriday = new DateTimeImmutable('next friday');
foreach(getGenerator($today, $nextFriday) as $datetime) {
// なにか処理
}
上記のコードは、DatePeriodで事足ります。
<?php
$today = new DateTimeImmutable();
$nextFriday = new DateTimeImmutable('next friday');
$interval = new DateInterval('P1D');
$iterator = new DatePeriod($today, $interval ,$nextFryday);
foreach($iterator as $datetime) {
// 何か処理
}
以下のどっちかの場合は、DatePeriodで対応できます。
- 「開始日」と「終了日」と「繰り返す回数」で、ループする
- 「開始日」と「終了日」と「繰り返しごとの時間差」で、ループする
DateTimeを使う例
DatePeriodで対応できない、要素数たくさんなイテレータ
要素数が数百程度のイテレータなら、配列かなにかに詰め込んでおけばいいです。
しかし、例えばデータベースにある1億件のデータに対しての処理で、条件分岐がたくさんあるときは、DateTime型でミュータブルなオブジェクトが役立ちます。
<?php
function get() {
$datetime = new DateTime();
$counter = 0;
do{
$diffDaysString = "P{$counter}D";
yield $datetime->add(new DateInterval($diffDaysString));
$counter++;
} while($counter < 1000 * 1000);
}
foreach(get() as $datetime) {
// なんか処理
}