PHP の DateTime クラス - オブジェクト指向で日時を扱う
date 関数や strtotime 関数は手軽ですが、日時の比較・加減算・フォーマット変換を組み合わせるとコードが煩雑になりがちです。DateTime クラスはこれらの操作をオブジェクト指向でまとめて扱える仕組みを提供しています。
DateTime オブジェクトの生成
コンストラクタに日時文字列を渡すと、その日時を表す DateTime オブジェクトが生成されます。
$dt = new DateTime('2025-07-01 14:30:00');
echo $dt->format('Y-m-d H:i:s');
// 2025-07-01 14:30:00引数を省略すると現在日時で初期化されます。
$now = new DateTime();
echo $now->format('Y-m-d H:i:s');
// 例: 2025-06-15 14:30:00コンストラクタに渡せる文字列は strtotime と同じ形式に対応しているため、「now」「tomorrow」「+3 days」のような相対表現も受け付けます。
format メソッド
format メソッドは date 関数と同じフォーマット文字を使って日時を文字列に変換します。
$dt = new DateTime('2025-07-01');
echo $dt->format('Y年n月j日'); // 2025年7月1日
echo $dt->format('D, M j, Y'); // Tue, Jul 1, 2025
echo $dt->format('U'); // Unixタイムスタンプdate 関数との違いは、format がオブジェクトの持つ日時に対して動作する点です。date 関数ではタイムスタンプを引数で渡す必要がありましたが、DateTime ではオブジェクト自身が日時情報を保持しています。
modify メソッドで日時を変更する
modify メソッドは strtotime と同じ相対表現を受け取り、オブジェクトの日時を変更します。
$dt = new DateTime('2025-07-01');
$dt->modify('+10 days');
echo $dt->format('Y-m-d');
// 2025-07-11
$dt->modify('-3 months');
echo $dt->format('Y-m-d');
// 2025-04-11modify はオブジェクト自身を変更する(破壊的な操作)点に注意が必要です。元の日時を保持したい場合は、modify を呼ぶ前に clone で複製を作っておきます。
$original = new DateTime('2025-07-01');
$modified = clone $original;
$modified->modify('+10 days');
echo $original->format('Y-m-d'); // 2025-07-01(変わらない)
echo $modified->format('Y-m-d'); // 2025-07-11createFromFormat で書式を指定して解析する
文字列の書式が決まっている場合、createFromFormat を使えば解析ルールを明示的に指定できます。
$dt = DateTime::createFromFormat('Y/m/d H:i', '2025/07/01 09:00');
echo $dt->format('Y-m-d H:i:s');
// 2025-07-01 09:00:00第 1 引数にフォーマット文字列、第 2 引数に解析対象の文字列を渡します。strtotime では解析できない形式の文字列でも、書式を指定すれば正しく読み取れます。
// 日本語の日付を解析する
$dt = DateTime::createFromFormat('Y年m月d日', '2025年07月01日');
echo $dt->format('Y-m-d');
// 2025-07-01strtotime が対応しない日本語の日時文字列も、createFromFormat なら書式を明示することで解析可能です。解析に失敗した場合は false が返るため、戻り値のチェックを忘れないようにしてください。
日時の比較
DateTime オブジェクト同士は比較演算子で直接比較できます。
$a = new DateTime('2025-07-01');
$b = new DateTime('2025-08-15');
var_dump($a < $b); // true
var_dump($a == $b); // false
var_dump($a > $b); // falseタイムスタンプを取り出して数値比較をする手間がなく、コードの意図が明確になります。
diff メソッドで日時の差を求める
diff メソッドは 2 つの DateTime オブジェクトの差を DateInterval オブジェクトとして返します。
$start = new DateTime('2025-01-01');
$end = new DateTime('2025-07-15');
$diff = $start->diff($end);
echo $diff->y . '年' . $diff->m . 'か月' . $diff->d . '日';
// 0年6か月14日
echo $diff->days . '日間';
// 195日間diff->m で月数、$diff->d で日数をそれぞれ取得できる。これらは繰り上がり後の値なので、m は 0〜11 の範囲に収まる。
$diff->days は年月に分解せず、純粋な通算日数を返す。「あと何日」のようなカウントダウン表示に適している。
タイムゾーンを指定する
DateTime のコンストラクタの第 2 引数に DateTimeZone オブジェクトを渡すと、そのタイムゾーンで初期化されます。
$tokyo = new DateTime('now', new DateTimeZone('Asia/Tokyo'));
$utc = new DateTime('now', new DateTimeZone('UTC'));
echo $tokyo->format('Y-m-d H:i:s T');
// 例: 2025-06-15 23:30:00 JST
echo $utc->format('Y-m-d H:i:s T');
// 例: 2025-06-15 14:30:00 UTCタイムゾーンを変更したい場合は setTimezone メソッドを使います。
$dt = new DateTime('2025-07-01 12:00:00', new DateTimeZone('UTC'));
$dt->setTimezone(new DateTimeZone('Asia/Tokyo'));
echo $dt->format('Y-m-d H:i:s T');
// 2025-07-01 21:00:00 JSTUTC の 12:00 が日本時間の 21:00 に変換されています。内部のタイムスタンプは同じまま、表示上のタイムゾーンだけが切り替わる仕組みです。
setDate・setTime で個別に設定する
日付と時刻をそれぞれ個別に変更するメソッドも用意されています。
$dt = new DateTime();
$dt->setDate(2025, 12, 25);
$dt->setTime(18, 0, 0);
echo $dt->format('Y-m-d H:i:s');
// 2025-12-25 18:00:00setDate は年・月・日の 3 引数、setTime は時・分・秒の 3 引数を取ります。mktime のような引数順序の混乱がなく、メソッド名から操作内容が明確に読み取れるのが利点です。
getTimestamp でタイムスタンプを取得する
DateTime オブジェクトから Unix タイムスタンプを取り出したいときは getTimestamp メソッドを使います。
$dt = new DateTime('2025-07-01 00:00:00');
echo $dt->getTimestamp();
// 例: 1751295600date 関数や mktime と連携する必要がある場面で、DateTime オブジェクトとタイムスタンプの相互変換が簡単に行えます。