こんにちは、かつコーチです。
前回は文字列操作の関数をまとめて解説しました。
今回は、投稿日時の表示や会員登録日の記録など、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() に渡す書式指定文字の代表例をまとめておきます。
| 指定文字 | 意味 | 出力例 |
|---|---|---|
Y | 4桁の年 | 2026 |
m | 2桁の月 | 08 |
d | 2桁の日 | 11 |
H | 24時間表記の時 | 15 |
i | 分 | 30 |
s | 秒 | 00 |
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 オブジェクトは、= で代入しても値がコピーされるのではなく、同じオブジェクトを指し示す状態になります。
そのため $trialEnd を modify() すると、参照元である $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を使ってフォームの値を受け取る方法