[PHP]date_create_immutable関数の完全解説!不変な日付オブジェクトの使い方

こんにちは!今回はPHPのdate_create_immutable関数について、実践的な例を交えながら詳しく解説します。

目次

  1. date_create_immutable関数とは
  2. 基本的な使い方
  3. 実践的な使用例
  4. 通常のDateTimeとの違い

date_create_immutable関数とは?

DateTimeImmutableオブジェクトを作成するPHP関数です。一度作成すると変更できない(イミュータブルな)日付オブジェクトを生成します。

基本的な使い方

1. 基本的な生成

// 現在の日時でオブジェクトを作成
$date = date_create_immutable();
echo $date->format('Y-m-d H:i:s');

// 特定の日付でオブジェクトを作成
$date = date_create_immutable('2024-01-01');
echo $date->format('Y-m-d');

2. タイムゾーン指定

$tz = new DateTimeZone('Asia/Tokyo');
$date = date_create_immutable('2024-01-01', $tz);
echo $date->format('Y-m-d H:i:s T');

実践的な使用例

1. 日付の計算

function addDays($date, $days) {
    // 元のオブジェクトは変更されず、新しいオブジェクトが返される
    $newDate = $date->modify("+{$days} days");
    return $newDate->format('Y-m-d');
}

$date = date_create_immutable('2024-01-01');
echo addDays($date, 5); // 2024-01-06
echo $date->format('Y-m-d'); // 2024-01-01(元の日付は変更されない)

2. 日付の比較

function compareDates($date1, $date2) {
    $d1 = date_create_immutable($date1);
    $d2 = date_create_immutable($date2);

    return [
        'equals' => $d1 == $d2,
        'before' => $d1 < $d2,
        'after' => $d1 > $d2
    ];
}

// 使用例
print_r(compareDates('2024-01-01', '2024-02-01'));

3. 日付の範囲チェック

class DateRange {
    private $start;
    private $end;

    public function __construct($start, $end) {
        $this->start = date_create_immutable($start);
        $this->end = date_create_immutable($end);
    }

    public function contains($date) {
        $checkDate = date_create_immutable($date);
        return $checkDate >= $this->start && 
               $checkDate <= $this->end;
    }
}

// 使用例
$range = new DateRange('2024-01-01', '2024-12-31');
echo $range->contains('2024-06-15') ? 'Yes' : 'No';

4. 日付の連続処理

class DateProcessor {
    private $date;

    public function __construct($dateString) {
        $this->date = date_create_immutable($dateString);
    }

    public function addDays($days) {
        $this->date = $this->date->modify("+{$days} days");
        return $this;
    }

    public function addMonths($months) {
        $this->date = $this->date->modify("+{$months} months");
        return $this;
    }

    public function getDate() {
        return $this->date->format('Y-m-d');
    }
}

// 使用例
$processor = new DateProcessor('2024-01-01');
echo $processor->addDays(5)
              ->addMonths(2)
              ->getDate();

5. エラーハンドリング

function createSafeDate($dateString) {
    try {
        $date = date_create_immutable($dateString);
        if ($date === false) {
            throw new Exception('Invalid date format');
        }
        return $date;
    } catch (Exception $e) {
        return null;
    }
}

DateTimeとDateTimeImmutableの違い

1. 変更の動作

// DateTime(ミュータブル)
$dateTime = new DateTime('2024-01-01');
$modified = $dateTime->modify('+1 day');
echo $dateTime->format('Y-m-d'); // 2024-01-02(元のオブジェクトが変更される)

// DateTimeImmutable(イミュータブル)
$dateImmutable = new DateTimeImmutable('2024-01-01');
$modified = $dateImmutable->modify('+1 day');
echo $dateImmutable->format('Y-m-d'); // 2024-01-01(元のオブジェクトは変更されない)

2. メソッドチェーン

function processDate($date) {
    return $date
        ->modify('+1 day')
        ->modify('+1 month')
        ->format('Y-m-d');
}

$immutable = date_create_immutable('2024-01-01');
echo processDate($immutable);

ベストプラクティス

1. イミュータブルオブジェクトの活用

class Event {
    private $startDate;

    public function __construct($date) {
        $this->startDate = date_create_immutable($date);
    }

    public function getEndDate($duration) {
        return $this->startDate->modify("+{$duration} days");
    }
}

2. 日付の比較と検証

function isValidPeriod($start, $end) {
    $startDate = date_create_immutable($start);
    $endDate = date_create_immutable($end);

    return $startDate <= $endDate;
}

注意点

  1. パフォーマンスへの配慮
  2. メモリ使用量の考慮
  3. エラーハンドリングの実装
  4. タイムゾーンの適切な設定

まとめ

date_create_immutable関数は、安全な日付処理を実現するための強力なツールです。
以下のポイントを押さえておきましょう:

  • イミュータブルな性質を活用
  • 適切なエラーハンドリング
  • メソッドチェーンの活用
  • 日付の妥当性検証

以上でdate_create_immutable関数の解説を終わります!
ご質問があればお気軽にどうぞ!

タイトルとURLをコピーしました