PHPで日付・時刻を扱う:DateTimeクラスの基本

phpアイキャッチ PHP

こんにちは、かつコーチです。

前回は文字列操作の関数をまとめて解説しました。

今回は、投稿日時の表示や会員登録日の記録など、Webアプリケーションでほぼ必ず登場する「日付・時刻」の扱い方を解説します。

PHPには古くからある date() 関数と、比較的新しい DateTime クラスの2種類の書き方がありますが、今回は実務でも扱いやすい DateTime クラスを中心に見ていきます。

私自身、DateTime の存在を知らずに date() と文字列の計算だけで日付処理を無理やり書いていた時期があり、後から知って「もっと早く知りたかった」と感じた機能なので、ぜひ最初から押さえておいてください。

PHPで日付を扱う2つの方法

date() 関数との違い

PHPで日付を扱う一番シンプルな方法は date() 関数です。

<?php
echo date("Y-m-d");
// 出力例: 2026-08-11

date() は「今の日時を指定した書式の文字列で取得する」ことに特化した関数で、手軽に使えるのが魅力です。

ただし、「1週間後の日付を計算したい」「2つの日付の差を求めたい」といった日付同士の計算が必要になると、date() だけでは書き方が複雑になりがちです。

そこで登場するのが DateTime クラスです。

DateTime クラスとは

クラスとは、関連するデータと処理をひとまとめにした設計図のようなものです(詳しくはオブジェクト指向の記事で解説します)。

DateTime は「日付・時刻」を表すための専用クラスで、日付の計算や比較を直感的に書けるように設計されています。

<?php
$now = new DateTime();
echo $now->format("Y-m-d H:i:s");
// 出力例: 2026-08-11 15:30:00

new DateTime() で「今この瞬間の日時」を持ったオブジェクトを作り、format() で好きな書式に変換して表示しています。

DateTimeの基本的な使い方

日付を指定してオブジェクトを作る

現在時刻ではなく、特定の日付を指定して DateTime オブジェクトを作ることもできます。

<?php
$birthday = new DateTime("2000-04-01");
echo $birthday->format("Y年m月d日");
// 出力: 2000年04月01日

new DateTime("2000-04-01") のように、コンストラクタ(オブジェクトを作るときの初期設定処理)に日付の文字列を渡すだけで指定できます。

よく使う書式指定文字

format() に渡す書式指定文字の代表例をまとめておきます。

指定文字意味出力例
Y4桁の年2026
m2桁の月08
d2桁の日11
H24時間表記の時15
i30
s00
D曜日(英語省略形)Tue
<?php
$date = new DateTime("2026-08-11");
echo $date->format("Y/m/d (D)");
// 出力: 2026/08/11 (Tue)

よく使う組み合わせなので、いくつかは覚えてしまうと便利です。

日付の計算をする

日付を加算・減算する:modify

日付の計算をしたいときは modify() メソッドを使います。

<?php
$date = new DateTime("2026-08-11");
$date->modify("+7 days");
echo $date->format("Y-m-d");
// 出力: 2026-08-18

"+7 days"(7日後)や "-1 month"(1ヶ月前)のように、人間が読める形式で日付の増減を指定できます。

会員登録から30日後を「無料お試し期間の終了日」として計算する、といった場面で重宝します。

<?php
$registeredAt = new DateTime("2026-08-11");
$trialEnd = clone $registeredAt;
$trialEnd->modify("+30 days");

echo "登録日: " . $registeredAt->format("Y-m-d") . "\n";
echo "お試し終了日: " . $trialEnd->format("Y-m-d") . "\n";
// 登録日: 2026-08-11
// お試し終了日: 2026-09-10

つまずきポイント:clone を忘れて元の値まで変わってしまう

先ほどのコードで clone を使っているのには理由があります。

私が最初に DateTime を使い始めた頃、clone の必要性を知らず、次のようなコードを書いて痛い目を見たことがあります。

❌ Before:clone せずにオブジェクトをそのまま使い回す

<?php
$registeredAt = new DateTime("2026-08-11");
$trialEnd = $registeredAt; // cloneせずに代入
$trialEnd->modify("+30 days");

echo "登録日: " . $registeredAt->format("Y-m-d") . "\n";
echo "お試し終了日: " . $trialEnd->format("Y-m-d") . "\n";
// 登録日: 2026-09-10 ← 元の登録日まで変わってしまっている!
// お試し終了日: 2026-09-10

DateTime オブジェクトは、= で代入しても値がコピーされるのではなく、同じオブジェクトを指し示す状態になります。

そのため $trialEndmodify() すると、参照元である $registeredAt の値まで一緒に変わってしまうのです。

私はこのバグのせいで、会員の登録日が謎に書き換わるという不具合を出してしまい、原因を突き止めるのにかなり苦戦しました。

✅ After:clone してから操作する

<?php
$registeredAt = new DateTime("2026-08-11");
$trialEnd = clone $registeredAt; // cloneして別オブジェクトとしてコピーする
$trialEnd->modify("+30 days");

echo "登録日: " . $registeredAt->format("Y-m-d") . "\n";
echo "お試し終了日: " . $trialEnd->format("Y-m-d") . "\n";
// 登録日: 2026-08-11 ← 元の値は変わらない
// お試し終了日: 2026-09-10

clone を使うことで、元のオブジェクトとは別の「独立したコピー」を作れます。

DateTime を使って計算した結果を別の変数に持たせたい場合は、clone を忘れないようにしましょう。

2つの日付の差を求める:diff

2つの日付の間が何日空いているかを調べたいときは diff() メソッドを使います。

<?php
$start = new DateTime("2026-08-01");
$end = new DateTime("2026-08-11");
$interval = $start->diff($end);

echo $interval->days . "日間";
// 出力: 10日間

diff() の結果は DateInterval という別のオブジェクトで返ってきて、days(合計日数)や y(年数)、m(月数)といったプロパティで細かい情報を取り出せます。

実務でよく使う場面

会員登録日から経過日数を計算する

DateTime の使い方がひと通り分かったところで、実務でよくある「経過日数の計算」を組み立ててみましょう。

<?php
$registeredAt = new DateTime("2026-07-01");
$now = new DateTime();
$interval = $registeredAt->diff($now);

echo "登録から " . $interval->days . " 日が経過しています";

こうしたコードは、会員ランクの自動判定や、無料期間の残り日数表示などにそのまま応用できます。

タイムゾーンには要注意

サーバーの設定によっては、意図しないタイムゾーンで日時が扱われてしまうことがあります。

<?php
date_default_timezone_set("Asia/Tokyo");

$now = new DateTime();
echo $now->format("Y-m-d H:i:s");

date_default_timezone_set("Asia/Tokyo") を処理の最初に書いておくことで、日本時間を基準に日時を扱えるようになります。

海外のレンタルサーバーを使っている場合など、タイムゾーンの設定を忘れると「投稿時刻が9時間ずれる」といった不具合につながるので、忘れずに設定しておきましょう。

まとめ

この記事のポイント

  • 単純な日時の表示は date()、計算や比較が必要なら DateTime クラスが便利
  • new DateTime("日付文字列") で任意の日時のオブジェクトを作れる
  • modify() で日付の加算・減算、diff() で日付同士の差を求められる
  • DateTime オブジェクトは代入すると参照が共有されるため、独立させたい場合は clone を使う
  • タイムゾーンは date_default_timezone_set() で明示的に設定しておくと安全

次に読むべき記事

日付の扱い方が分かったところで、次はフォームから送られてきた値をPHPで受け取る方法を見ていきましょう。

→ 次の記事:PHPで_GET・_POSTを使ってフォームの値を受け取る方法

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