- カテゴリ: PHP
- 掲載バージョン: PHP 8.4
- 名前空間 / FQCN / コマンド:
date(string $format, ?int $timestamp = null): string|false - 関連: DateTimeImmutable::format / strtotime / time / gmdate / date_default_timezone_set / IntlDateFormatter
- 変更履歴: PHP 8.1 以降、関連の
strftime()が非推奨。date()本体の仕様は大きな変更なし。
要点(TL;DR)
- UNIXタイムスタンプを指定のフォーマット文字で整形して返す。
- 最低限:
echo date('Y-m-d H:i:s'); - 罠:
- タイムゾーン未設定で警告/期待しない時刻になる
m(月)とi(分)、H(24時)とh(12時)の取り違え- ミリ秒のまま渡して 1970-01-01 になる(ms→s 変換漏れ)
概要
date() は現在時刻または指定した UNIX タイムスタンプを、Y-m-d H:i:s のようなフォーマットで文字列化します。画面表示、ログファイル名、HTTP ヘッダ生成など、人間向けの固定フォーマット文字列が必要な場面で使います。ロケール依存の月名/曜日名が必要なら IntlDateFormatter を検討します。
構文 / シグネチャ
string|false date(string $format, ?int $timestamp = null)
- 引数(表)
| 引数 | 型 | 必須 | 既定値 | 説明 |
|---|---|---|---|---|
$format | string | はい | — | 書式指定(例 Y-m-d H:i:s、c、r など)。不明な文字はそのまま出力。 |
$timestamp | int|null | いいえ | null | UNIX秒。null なら現在時刻。 |
- 戻り値:
string(整形済み文字列)。範囲外のタイムスタンプなどでごくまれにfalse。 - 例外/副作用:
- 例外は投げません。
- タイムゾーン未設定時に警告(E_WARNING)や期待外の時刻になることあり。
- 32bit 環境では 2038 年問題の影響で範囲制限。
使用例
最小例
<?php
declare(strict_types=1);
date_default_timezone_set('Asia/Tokyo'); // 明示推奨
echo date('Y-m-d H:i:s'); // 例: 2025-09-08 09:41:23
実務例:日次ローテートのログファイル名+HTTPヘッダ
<?php
declare(strict_types=1);
date_default_timezone_set('Asia/Tokyo');
// 日次ローテート用ファイル名
$logPath = __DIR__ . '/logs/app-' . date('Y-m-d') . '.log';
// UTC の Last-Modified ヘッダ(HTTPはUTCが基本)
$lastModified = gmdate('D, d M Y H:i:s') . ' GMT';
header('Last-Modified: ' . $lastModified);
// 文字列→時刻の解釈と併用(ユーザー入力など)
$input = '2025-10-01 10:30';
$ts = strtotime($input); // 失敗時は false
if ($ts !== false) {
echo date('c', $ts); // ISO 8601: 2025-10-01T10:30:00+09:00
}
(例外処理を伴う堅牢案:ユーザー指定のタイムゾーンを検証してから date_default_timezone_set、あるいは DateTimeImmutable + ->format() を使用)
よくある落とし穴・注意
- タイムゾーン:
date_default_timezone_set()またはphp.iniのdate.timezoneを設定。未設定だと警告や意図しない時刻に。 - 書式指定の取り違え:
m=月(01–12) /i=分(00–59)H=24時 /h=12時(a/Aと併用)
- ミリ秒誤用:JSの
Date.now()はミリ秒。PHPのdate()は秒。intval($ms/1000)にする。 - DST(夏時間):ローカル時刻での 1時間欠落/重複に注意。UTC基準にしたい場面は
gmdate()を使う。 - 32bit PHP:タイムスタンプ範囲が狭い(おおむね 1901–2038)。64bit または
DateTimeImmutableを。 - ロケール表記:月名・曜日名の日本語化は
date()では不可。IntlDateFormatterを使う。 - エラー形態:警告(E_WARNING)発生あり/戻り値
falseになる可能性あり(型宣言は考慮)。
PHP 8.1–8.4 差分メモ
- 8.1:
strftime()非推奨(ロケール表記にはIntlDateFormatter推奨) - 8.2–8.4:
date()仕様の大きな変更はなし(タイムゾーンDB更新は随時)
代替・関連APIとの比較
DateTimeImmutable::format():明示的なDateTimeZoneと組み合わせてテストしやすい/安全。新規実装ではこちら推奨。gmdate():常に UTC。HTTP ヘッダや署名用に。IntlDateFormatter(ext-intl):ロケールに応じた「月/曜日名」の多言語表記。UI向け。Carbon(Laravel):連鎖的操作・人間可読(diffForHumans)。内部はDateTime系。
テスト例(Pest)
<?php
it('formats a given timestamp deterministically', function () {
date_default_timezone_set('UTC');
expect(date('Y-m-d', 0))->toBe('1970-01-01');
expect(date('H:i', 3600))->toBe('01:00'); // 1970-01-01 01:00:00 UTC
});
トラブルシュート(エラー別)
| 症状/エラー | 原因 | 対処 |
|---|---|---|
Warning: date(): It is not safe to rely on the system's timezone settings. | タイムゾーン未設定 | date_default_timezone_set('Asia/Tokyo') または php.ini で date.timezone を設定 |
| 表示が 1970-01-01 になる | ミリ秒をそのまま渡した | intval($ms/1000) に変換 |
| 月と分を取り違えた表示 | m と i の混同 | フォーマットを見直し(分は i) |
| 日本語の曜日・月名にできない | date() はロケール非対応 | IntlDateFormatter を使用 |
| 古い日付/遠い未来で失敗 | 32bit PHP の範囲外 | 64bit PHP / DateTimeImmutable を使用 |

