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-11

modify はオブジェクト自身を変更する(破壊的な操作)点に注意が必要です。元の日時を保持したい場合は、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-11

createFromFormat で書式を指定して解析する

文字列の書式が決まっている場合、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-01

strtotime が対応しない日本語の日時文字列も、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 の範囲に収まる。

days で通算日数を取得

$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 JST

UTC の 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:00

setDate は年・月・日の 3 引数、setTime は時・分・秒の 3 引数を取ります。mktime のような引数順序の混乱がなく、メソッド名から操作内容が明確に読み取れるのが利点です。

getTimestamp でタイムスタンプを取得する

DateTime オブジェクトから Unix タイムスタンプを取り出したいときは getTimestamp メソッドを使います。

$dt = new DateTime('2025-07-01 00:00:00');
echo $dt->getTimestamp();
// 例: 1751295600

date 関数や mktime と連携する必要がある場面で、DateTime オブジェクトとタイムスタンプの相互変換が簡単に行えます。