導入
PHPで日付や時刻を扱う際、何気なく「DateTime」クラスを使っていませんか?DateTimeクラスは便利な反面、メソッドを呼び出すたびに元のインスタンス自体が書き換わってしまう(破壊的変更)という特性があります。これにより、意図しない場所で日付が変更され、バグの原因となることが多々あります。本記事では、この課題を解決する「DateTimeImmutable」の活用法と、実務で役立つ「今週末の日付を取得する」具体的な実装方法を解説します。
基礎知識
「DateTimeImmutable」とは、その名の通り「不変(Immutable)」なDateTimeクラスです。
通常、DateTimeクラスでadd()メソッドなどを使って日時を操作すると、オブジェクト自体の値が更新されます。一方、DateTimeImmutableクラスは、計算を行うと常に「新しいインスタンス」を返します。
これにより、計算前の日付データを保持したまま、計算結果だけを別変数に格納することが可能となり、副作用のない安全なコードを書くことができます。
実装/解決策
今週末(土曜日・日曜日)の日付を取得するには、現在の日曜日からの曜日番号(0:日〜6:土)を利用します。
現在の日付から「6 – 曜日番号」を計算することで、土曜日までの日数を算出できます。この日数をDateIntervalクラスで加算することで、正確な日付を導き出します。DateTimeImmutableを使うことで、計算過程で元の日付オブジェクトを汚染することなく処理を完結させます。
サンプルプログラム
以下のコードは、現在時刻を基準に、今週末の土曜日と日曜日の日付を算出する実用的なスニペットです。
format(‘w’);
// 土曜日までの差分日数を計算
$diffToSat = 6 – $w;
// 土曜日を算出(元の$nowは変更されないため安全)
$sat = $now->add(new DateInterval(‘P’ . $diffToSat . ‘D’));
// 日曜日を算出(土曜日の翌日として計算)
$sun = $sat->add(new DateInterval(‘P1D’));
// 結果を表示
echo “今日: ” . $now->format(‘Y-m-d’) . PHP_EOL;
echo “今週末の土曜日: ” . $sat->format(‘Y-m-d’) . PHP_EOL;
echo “今週末の日曜日: ” . $sun->format(‘Y-m-d’) . PHP_EOL;
// 補足:既存のDateTimeから変換する場合
$mutable = new DateTime();
$immutable = DateTimeImmutable::createFromMutable($mutable);
?>
応用・注意点
1. 既存資産との付き合い方
もし既存のシステムでDateTimeクラスが使われている場合でも、`DateTimeImmutable::createFromMutable($date)` を使えば、その場で不変オブジェクトへ変換可能です。レガシーコードの改修時には非常に有用です。
2. タイムゾーンの考慮
実務ではサーバーのタイムゾーン設定に依存しないよう、インスタンス生成時に `new DateTimeImmutable(‘now’, new DateTimeZone(‘Asia/Tokyo’))` のように明示的にタイムゾーンを指定することをおすすめします。
3. バグ回避の鉄則
PHP 5.6以降であればDateTimeImmutableが利用可能です。現代のPHP開発においては、特別な理由がない限り「DateTimeではなくDateTimeImmutableを使う」ことをコーディング規約としてチームで共有しておくと、日付関連の不具合を大幅に減らすことができます。