LoginSignup
64
65

More than 3 years have passed since last update.

普段はDateTimeImmutableを使え、DateTimeはやめとけ

Last updated at Posted at 2016-06-15

まとめ

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) {
    // なんか処理
}
64
65
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
64
65