- PHP
PHP date関数フォーマット一覧|DateTimeでの日付計算も解説
PHPのdate関数とは、date('Y-m-d H:i:s') のようにフォーマット文字を並べて、日付や時刻を好きな形の文字列にする関数です。 同じフォーマット文字は DateTime や DateTimeImmutable の format() メソッドでもそのまま使えます。
この記事では、フォーマット文字の全一覧を実際の出力例つきでまとめ、「2026年3月7日」「2026/03/07 09:05」のようなよく使う書式の逆引き表を用意しました。後半では、1月31日 に +1 month を足すと3月になる月末の動きを再現し、回避するコードを紹介します。日数差、曜日の日本語表示、和暦、タイムゾーン変換まで、すべて PHP 8.4.21 で実行した結果を載せています。
date関数フォーマットの早見表
まずは、最もよく使う書式の逆引きです。出力例は 2026-03-07 09:05:03(土曜日、タイムゾーンは Asia/Tokyo)を整形した結果です。
| 欲しい形 | フォーマット | 出力例 |
|---|---|---|
| 年-月-日 | Y-m-d |
2026-03-07 |
| 年/月/日 | Y/m/d |
2026/03/07 |
| 日本語(ゼロなし) | Y年n月j日 |
2026年3月7日 |
| 日本語(ゼロあり・時刻つき) | Y年m月d日 H時i分s秒 |
2026年03月07日 09時05分03秒 |
| 日時(DBのDATETIME型と同じ形) | Y-m-d H:i:s |
2026-03-07 09:05:03 |
| 日時(秒なし) | Y/m/d H:i |
2026/03/07 09:05 |
| 時刻だけ | H:i |
09:05 |
| 12時間表記 | g:i A |
9:05 AM |
| 区切りなし(ファイル名向け) | Ymd / YmdHis |
20260307 / 20260307090503 |
| 年月だけ | Y-m |
2026-03 |
| 月初の日付 | Y-m-01 |
2026-03-01 |
| 月末の日付 | Y-m-t |
2026-03-31 |
| ISO 8601(APIのやり取り向け) | c または Y-m-d\TH:i:sP |
2026-03-07T09:05:03+09:00 |
| ミリ秒つき | Y-m-d H:i:s.v |
2026-03-07 09:05:03.123 |
| 英語表記 | l, F jS, Y |
Saturday, March 7th, 2026 |
| 短い和式 | y.n.j |
26.3.7 |
| UNIXタイムスタンプ | U |
1772841903 |
| ISO週番号つき | o-\WW-N |
2026-W10-6 |
使い方は2通りあり、どちらも同じフォーマット文字を使います。
| 書き方 | コード | 向いている場面 |
|---|---|---|
| 関数 | date('Y-m-d') / date('Y-m-d', $timestamp) |
現在日時をさっと表示する |
| クラス | (new DateTimeImmutable('2026-03-07'))->format('Y-m-d') |
日付の計算・比較・タイムゾーン変換を行う |
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「PHP date関数フォーマット一覧|DateTimeでの日付計算も解説」
動作確認した環境とコードの前提
出力はすべて次の環境で実行した結果です。
| 項目 | 内容 |
|---|---|
| PHP | 8.4.21(CLI) |
| intl拡張 | 有効(ICU 74.2) |
| タイムゾーン | コードの先頭で Asia/Tokyo を指定 |
この記事のコードは、先頭に次の1行がある前提です。タイムゾーンを指定しないと、サーバーの設定(今回の環境では UTC)で表示され、日本時間と9時間ずれます。
<?php
date_default_timezone_set('Asia/Tokyo');
フォーマット文字の全一覧
2026-03-07 09:05:03.123456(土曜日)を1文字ずつ整形した出力です。大文字と小文字で意味が変わるので、表で確認しながら使ってください。
<?php
date_default_timezone_set('Asia/Tokyo');
$dt = new DateTimeImmutable('2026-03-07 09:05:03.123456');
foreach (str_split('dDjlNSwzWFmMntLoXxYyaABgGhHisuveIOPpTZcrU') as $c) {
echo $c, "\t", $dt->format($c), PHP_EOL;
}
日
| 文字 | 意味 | 出力例 |
|---|---|---|
d |
日(2桁、ゼロあり) | 07 |
j |
日(ゼロなし) | 7 |
D |
曜日(英語3文字) | Sat |
l(小文字のエル) |
曜日(英語フルスペル) | Saturday |
N |
曜日の番号(月曜=1 〜 日曜=7) | 6 |
w |
曜日の番号(日曜=0 〜 土曜=6) | 6 |
S |
日の英語の接尾辞(st, nd, rd, th) | th |
z |
年の初めからの日数(0始まり) | 65 |
週・月
| 文字 | 意味 | 出力例 |
|---|---|---|
W |
ISO 8601 の週番号 | 10 |
F |
月(英語フルスペル) | March |
M |
月(英語3文字) | Mar |
m |
月(2桁、ゼロあり) | 03 |
n |
月(ゼロなし) | 3 |
t |
その月の日数 | 31 |
年
| 文字 | 意味 | 出力例 |
|---|---|---|
Y |
年(4桁) | 2026 |
y |
年(下2桁) | 26 |
L |
うるう年なら 1、そうでなければ 0 | 0 |
o |
ISO 8601 の週番号に対応する年 | 2026 |
X |
符号つきの拡張表記の年(PHP 8.2以降) | +2026 |
x |
可能なら符号なしの拡張表記の年(PHP 8.2以降) | 2026 |
時・分・秒
| 文字 | 意味 | 出力例 |
|---|---|---|
H |
時(24時間、2桁) | 09 |
G |
時(24時間、ゼロなし) | 9 |
h |
時(12時間、2桁) | 09 |
g |
時(12時間、ゼロなし) | 9 |
i |
分(2桁) | 05 |
s |
秒(2桁) | 03 |
a |
午前・午後(小文字) | am |
A |
午前・午後(大文字) | AM |
v |
ミリ秒(3桁) | 123 |
u |
マイクロ秒(6桁) | 123456 |
B |
スウォッチ・インターネットタイム | 045 |
date() 関数は整数のタイムスタンプを受け取るため、date('u') は常に 000000、date('v') は常に 000 になりました。ミリ秒やマイクロ秒が必要なときは DateTimeImmutable を使います。
タイムゾーン・全体
| 文字 | 意味 | 出力例 |
|---|---|---|
e |
タイムゾーン名 | Asia/Tokyo |
T |
タイムゾーンの略称 | JST |
P |
UTCとの差(コロンあり) | +09:00 |
p |
P と同じ。ただし +00:00 のとき Z(PHP 8.0以降) |
+09:00 |
O |
UTCとの差(コロンなし) | +0900 |
Z |
UTCとの差(秒) | 32400 |
I(大文字のアイ) |
サマータイム中なら 1 | 0 |
c |
ISO 8601 形式の日時 | 2026-03-07T09:05:03+09:00 |
r |
RFC 2822 形式の日時 | Sat, 07 Mar 2026 09:05:03 +0900 |
U |
UNIXタイムスタンプ(秒) | 1772841903 |
間違えやすい組み合わせ
| 迷う文字 | 違い |
|---|---|
m と i |
m は月、i は分。H:m:s と書くと「時:月:秒」になる |
d と j |
d は 07、j は 7 |
m と n |
m は 03、n は 3 |
M と F |
M は Mar、F は March |
D と l |
D は Sat、l は Saturday |
H と h |
H は24時間、h は12時間 |
Y と o |
年末年始の数日だけ値が異なることがある。通常の年表示は Y |
w と N |
w は日曜が 0、N は日曜が 7 |
フォーマット文字をそのまま表示したいとき
フォーマット文字として解釈されたくない英字は、前に \ を付けます。日本語の文字はフォーマット文字ではないので、そのまま書けます。
echo $dt->format('\T\o\d\a\y \i\s l'), PHP_EOL;
echo $dt->format('Y年n月j日'), PHP_EOL;
Today is Saturday
2026年3月7日
定義済みの書式定数
よく使われる規格の書式は、定数として用意されています。
| 定数 | 出力例 |
|---|---|
DateTimeInterface::ATOM |
2026-03-07T09:05:03+09:00 |
DateTimeInterface::RFC3339 |
2026-03-07T09:05:03+09:00 |
DateTimeInterface::RFC3339_EXTENDED |
2026-03-07T09:05:03.123+09:00 |
DateTimeInterface::ISO8601 |
2026-03-07T09:05:03+0900 |
DateTimeInterface::RFC2822 |
Sat, 07 Mar 2026 09:05:03 +0900 |
DateTimeInterface::COOKIE |
Saturday, 07-Mar-2026 09:05:03 JST |
DateTimeInterface::RSS |
Sat, 07 Mar 2026 09:05:03 +0900 |
JSONのAPIで日時をやり取りするときは DateTimeInterface::ATOM(または c)を使うと、タイムゾーンの差まで含んだ形になります。
date・strtotime・mktimeの基本
関数だけで日付を扱うときは、次の3つを組み合わせます。
| 関数 | 役割 | 例 | 結果 |
|---|---|---|---|
time() |
現在のUNIXタイムスタンプ | time() |
整数(秒) |
date($format, $ts) |
タイムスタンプを文字列にする | date('Y-m-d', 0) |
1970-01-01(日本時間では 09:00:00) |
strtotime($文字列, $基準) |
文字列をタイムスタンプにする | strtotime('2026-10-02 +1 week') |
2026-10-09 のタイムスタンプ |
mktime(時, 分, 秒, 月, 日, 年) |
数値からタイムスタンプを作る | mktime(0, 0, 0, 3, 7, 2026) |
2026-03-07 のタイムスタンプ |
checkdate(月, 日, 年) |
存在する日付かを確かめる | checkdate(2, 29, 2026) |
false |
echo date('Y-m-d H:i:s', 0), PHP_EOL;
echo date('Y-m-d', strtotime('2026-10-02 +1 week')), PHP_EOL;
var_dump(strtotime('abc'));
1970-01-01 09:00:00
2026-10-09
bool(false)
strtotime() は読み取れない文字列に対して false を返します。 そのまま date() に渡すと false は 0 として扱われ、1970年1月1日が表示されます。画面に「1970/01/01」が出たときは、strtotime() の戻り値を確認すると原因が見つかります。
strtotimeで使える相対表現の一覧
基準を 2026-10-02 10:00:00(金曜日)にして、date('Y-m-d H:i:s (D)', strtotime($表現, $基準)) を実行した結果です。
| 表現 | 結果 |
|---|---|
now |
2026-10-02 10:00:00 (Fri) |
today |
2026-10-02 00:00:00 (Fri) |
tomorrow |
2026-10-03 00:00:00 (Sat) |
yesterday |
2026-10-01 00:00:00 (Thu) |
+1 day |
2026-10-03 10:00:00 (Sat) |
-3 days |
2026-09-29 10:00:00 (Tue) |
+1 week |
2026-10-09 10:00:00 (Fri) |
+1 month |
2026-11-02 10:00:00 (Mon) |
-1 year |
2025-10-02 10:00:00 (Thu) |
+2 hours 30 minutes |
2026-10-02 12:30:00 (Fri) |
next monday |
2026-10-05 00:00:00 (Mon) |
last friday |
2026-09-25 00:00:00 (Fri) |
friday(当日が金曜) |
2026-10-02 00:00:00 (Fri) |
next friday |
2026-10-09 00:00:00 (Fri) |
monday this week |
2026-09-28 00:00:00 (Mon) |
sunday this week |
2026-10-04 00:00:00 (Sun) |
first day of this month |
2026-10-01 10:00:00 (Thu) |
last day of this month |
2026-10-31 10:00:00 (Sat) |
first day of next month |
2026-11-01 10:00:00 (Sun) |
last day of next month |
2026-11-30 10:00:00 (Mon) |
last day of previous month |
2026-09-30 10:00:00 (Wed) |
first monday of next month |
2026-11-02 00:00:00 (Mon) |
last friday of this month |
2026-10-30 00:00:00 (Fri) |
first day of january this year |
2026-01-01 00:00:00 (Thu) |
midnight / noon |
2026-10-02 00:00:00 / 12:00:00 |
tomorrow noon |
2026-10-03 12:00:00 (Sat) |
表から読み取れるポイントは2つです。today や曜日名を指定すると時刻が 00:00:00 になり、+1 day や first day of は元の時刻(10:00:00)を保ちます。 また、tomorrow と +1 day は時刻の扱いが異なります。
存在しない日付は繰り上がる
echo date('Y-m-d', strtotime('2026-02-30')), PHP_EOL;
echo date('Y-m-d', mktime(0, 0, 0, 13, 1, 2026)), PHP_EOL;
echo date('Y-m-d', mktime(0, 0, 0, 3, 0, 2026)), PHP_EOL;
var_dump(checkdate(2, 29, 2026), checkdate(2, 29, 2028), checkdate(13, 1, 2026));
2026-03-02
2027-01-01
2026-02-28
bool(false)
bool(true)
bool(false)
2月30日 は 3月2日、13月 は翌年の 1月 に繰り上がります。3月0日 が 2月28日 になる性質は、月末日を求める方法としても使われます。入力された日付が実在するかを確かめたいときは checkdate() を使います。
DateTimeとDateTimeImmutableの使い方
日付の計算や比較には、クラスを使うと読みやすく書けます。関数との対応は次のとおりです。
| やりたいこと | 関数での書き方 | クラスでの書き方 |
|---|---|---|
| 現在日時 | time() |
new DateTimeImmutable() |
| 文字列から作る | strtotime('2026-10-02') |
new DateTimeImmutable('2026-10-02') |
| 数値から作る | mktime(0,0,0,10,2,2026) |
(new DateTimeImmutable())->setDate(2026,10,2)->setTime(0,0) |
| 書式を指定して読み取る | (なし) | DateTimeImmutable::createFromFormat('Y/m/d', '2026/10/02') |
| 整形する | date('Y-m-d', $ts) |
$dt->format('Y-m-d') |
| 足す・引く | strtotime('+1 day', $ts) |
$dt->modify('+1 day') / $dt->add(new DateInterval('P1D')) |
| 差を求める | ($ts2 - $ts1) / 86400 |
$dt1->diff($dt2)->days |
| 比較する | $ts1 < $ts2 |
$dt1 < $dt2 |
| タイムスタンプを得る | そのまま | $dt->getTimestamp() |
| タイムゾーンを変える | date_default_timezone_set() |
$dt->setTimezone(new DateTimeZone('UTC')) |
DateTimeは元の値が変わる
DateTime と DateTimeImmutable の違いは、計算したときに元のオブジェクトが変わるかどうかです。
// DateTime(ミュータブル=変更できる)
$start = new DateTime('2026-10-02');
$end = $start->modify('+7 days');
echo $start->format('Y-m-d'), ' / ', $end->format('Y-m-d'), PHP_EOL;
var_dump($start === $end);
// DateTimeImmutable(イミュータブル=変更されない)
$start = new DateTimeImmutable('2026-10-02');
$end = $start->modify('+7 days');
echo $start->format('Y-m-d'), ' / ', $end->format('Y-m-d'), PHP_EOL;
2026-10-09 / 2026-10-09
bool(true)
2026-10-02 / 2026-10-09
DateTime では、開始日のつもりだった $start まで7日後に変わりました。$start と $end は同じオブジェクトを指しています。DateTimeImmutable は計算のたびに新しいオブジェクトを返すので、元の値はそのまま残ります。
| クラス | modify() などの動き |
使いどころ |
|---|---|---|
DateTime |
自分自身を書き換える | 既存のコードに合わせる場合。コピーが必要なら clone する |
DateTimeImmutable |
新しいオブジェクトを返す | 新しく書くコードはこちらがおすすめ |
DateTime を使い続ける場合は、clone でコピーしてから計算します。
$s2 = new DateTime('2026-10-02');
$e2 = (clone $s2)->modify('+7 days');
echo $s2->format('Y-m-d'), ' / ', $e2->format('Y-m-d'), PHP_EOL;
2026-10-02 / 2026-10-09
一方、DateTimeImmutable では戻り値を受け取る必要があります。受け取らないと何も変わりません。
$im = new DateTimeImmutable('2026-10-02');
$im->modify('+1 day'); // 戻り値を受け取っていない
echo $im->format('Y-m-d'), PHP_EOL;
2026-10-02
足し算・引き算
$d = new DateTimeImmutable('2026-10-02');
echo $d->add(new DateInterval('P1Y2M10DT2H30M'))->format('Y-m-d H:i'), PHP_EOL;
echo $d->sub(new DateInterval('P10D'))->format('Y-m-d'), PHP_EOL;
echo $d->setDate(2027, 1, 15)->format('Y-m-d'), PHP_EOL;
echo (new DateTimeImmutable('2026-10-02 15:30'))->setTime(0, 0)->format('Y-m-d H:i'), PHP_EOL;
2027-12-12 02:30
2026-09-22
2027-01-15
2026-10-02 00:00
DateInterval の書式は P(期間)で始め、時刻の部分は T で区切ります。
| 書き方 | 意味 |
|---|---|
P1D |
1日 |
P2W |
2週間 |
P1M |
1か月 |
P1Y |
1年 |
PT1H |
1時間 |
PT30M |
30分(T のあとの M は分) |
P1Y2M10DT2H30M |
1年2か月10日と2時間30分 |
月末問題:1月31日に+1 monthで3月になる
日付計算で最もつまずきやすいのが、月末日に「1か月」を足す場面です。
$d = new DateTimeImmutable('2026-01-31');
echo $d->modify('+1 month')->format('Y-m-d'), PHP_EOL;
echo date('Y-m-d', strtotime('2026-01-31 +1 month')), PHP_EOL;
echo $d->add(new DateInterval('P1M'))->format('Y-m-d'), PHP_EOL;
2026-03-03
2026-03-03
2026-03-03
3つの書き方すべてで、2月ではなく3月3日になりました。 PHPは「月の数字を1つ増やす」→「2月31日」→「存在しないので繰り上げる(2月は28日までなので3日分あふれて3月3日)」という順で計算するためです。ほかの日付でも確かめました。
| 元の日付 | 操作 | 結果 | 理由 |
|---|---|---|---|
| 2026-01-31 | +1 month |
2026-03-03 | 2月31日 → 3日あふれる |
| 2024-01-31(うるう年) | +1 month |
2024-03-02 | 2月31日 → 2日あふれる |
| 2026-03-31 | -1 month |
2026-03-03 | 2月31日 → 3月3日(月が戻らない) |
| 2026-05-31 | +1 month |
2026-07-01 | 6月31日 → 7月1日 |
| 2024-02-29 | +1 year |
2025-03-01 | 2025年2月29日 → 3月1日 |
DateTime で1月31日から +1 month を繰り返すと、最初の1回で3日にずれたあと、そのまま毎月3日になりました。
03-03 04-03 05-03 06-03
回避方法1:first day of / last day of を使う
「翌月の月初」「翌月の月末」が欲しいだけなら、first day of と last day of を使うと月がずれません。
$d = new DateTimeImmutable('2026-01-31');
echo $d->modify('first day of next month')->format('Y-m-d'), PHP_EOL;
echo $d->modify('last day of next month')->format('Y-m-d'), PHP_EOL;
2026-02-01
2026-02-28
関数でも同じ表現が使えます。
$ts = strtotime('2026-01-31');
echo date('Y-m-d', strtotime('first day of next month', $ts)), PHP_EOL;
echo date('Y-m-d', strtotime('last day of next month', $ts)), PHP_EOL;
2026-02-01
2026-02-28
「来月」「先月」という月単位の集計では、先に first day of で1日にそろえてから月を動かすと覚えておくと安心です。
回避方法2:月末に収まるように足す関数を用意する
「毎月同じ日。ただしその日がない月は月末」という動きにしたいときは、次の関数が使えます。
function addMonths(DateTimeImmutable $date, int $months): DateTimeImmutable
{
$day = (int)$date->format('j');
$first = $date->modify('first day of this month')
->modify(($months >= 0 ? '+' : '') . $months . ' month');
$last = (int)$first->format('t'); // 移動先の月の日数
return $first->setDate((int)$first->format('Y'), (int)$first->format('n'), min($day, $last));
}
foreach ([['2026-01-31', 1], ['2026-01-31', 2], ['2026-03-31', -1], ['2024-01-31', 1],
['2026-10-15', 3], ['2026-11-30', 3], ['2026-12-31', 2]] as [$s, $m]) {
echo "$s $m => ", addMonths(new DateTimeImmutable($s), $m)->format('Y-m-d'), PHP_EOL;
}
2026-01-31 1 => 2026-02-28
2026-01-31 2 => 2026-03-31
2026-03-31 -1 => 2026-02-28
2024-01-31 1 => 2024-02-29
2026-10-15 3 => 2027-01-15
2026-11-30 3 => 2027-02-28
2026-12-31 2 => 2027-02-28
ポイントは、常に「最初の基準日」から月数を数えることです。前回の結果に1か月ずつ足していくと、2月で28日になったあと3月も28日になってしまうため、addMonths($基準日, 1)、addMonths($基準日, 2) のように基準日からの月数で求めます。
月末日を求める方法
| 方法 | コード | 2026年2月の結果 |
|---|---|---|
フォーマット文字 t |
date('t', strtotime('2026-02-01')) |
28 |
Y-m-t |
(new DateTimeImmutable('2026-02-10'))->format('Y-m-t') |
2026-02-28 |
last day of |
->modify('last day of this month')->format('Y-m-d') |
2026-02-28 |
うるう年の2028年2月では、date('t', strtotime('2028-02-01')) は 29 を返しました。
日数差・期間を求める
2つの日付の差は diff() で求めます。戻り値は DateInterval オブジェクトです。
$a = new DateTimeImmutable('2026-10-02');
$b = new DateTimeImmutable('2026-12-25');
$i = $a->diff($b);
echo $i->days, ' / ', $i->format('%mか月%d日'), ' / ', $i->format('%R%a日'), ' / invert=', $i->invert, PHP_EOL;
$i = $b->diff($a); // 逆向き
echo $i->days, ' ', $i->format('%R%a'), ' invert=', $i->invert, PHP_EOL;
84 / 2か月23日 / +84日 / invert=0
84 -84 invert=1
通算の日数は days、月と日に分けた「残りの日数」は d です。 この2つは別の値なので、取り違えないようにしましょう。
| プロパティ・書式 | 意味 | 上の例での値 |
|---|---|---|
$i->days / %a |
通算の日数 | 84 |
$i->y / %y |
年の部分 | 0 |
$i->m / %m |
月の部分 | 2 |
$i->d / %d |
日の部分(月を除いた残り) | 23 |
$i->h / %h、$i->i / %i |
時・分の部分 | 0 |
$i->invert / %R |
逆向きなら 1 / 符号(+ -) |
0 / + |
年齢・経過時間・比較
// 年齢(誕生日の前日なので、まだ36歳になっていない)
$birth = new DateTimeImmutable('1990-10-03');
echo '年齢: ', $birth->diff(new DateTimeImmutable('2026-10-02'))->y, PHP_EOL;
// 経過時間
$i = (new DateTimeImmutable('2026-10-02 09:00'))->diff(new DateTimeImmutable('2026-10-03 18:30'));
echo $i->format('%a日 %h時間 %i分'), PHP_EOL;
// 比較は演算子でそのまま書ける
var_dump($a < $b, $a == new DateTimeImmutable('2026-10-02 00:00:00'));
echo max($a, $b)->format('Y-m-d'), PHP_EOL;
年齢: 35
1日 9時間 30分
bool(true)
bool(true)
2026-12-25
期間内の日付を順に取り出す
DatePeriod を使うと、開始日から終了日の前日までを1日ずつ取り出せます。
$p = new DatePeriod(new DateTimeImmutable('2026-10-01'), new DateInterval('P1D'), new DateTimeImmutable('2026-10-05'));
foreach ($p as $day) {
echo $day->format('n/j'), ' ';
}
echo PHP_EOL;
// 2026年10月の平日(月〜金)の日数を数える
$c = 0;
foreach (new DatePeriod(new DateTimeImmutable('2026-10-01'), new DateInterval('P1D'), new DateTimeImmutable('2026-11-01')) as $day) {
if ((int)$day->format('N') < 6) {
$c++;
}
}
echo "平日数: $c", PHP_EOL;
10/1 10/2 10/3 10/4
平日数: 22
終了日そのものは含まれないので、月全体を回すときは終了日に翌月1日を指定します。祝日は含まれないため、必要な場合は祝日の一覧を別に用意して除外します。
今週の月曜日と日曜日
$n = new DateTimeImmutable('2026-10-02');
$ws = $n->modify('monday this week');
echo $ws->format('Y-m-d'), '〜', $ws->modify('+6 days')->format('Y-m-d'), PHP_EOL;
echo (new DateTimeImmutable('2026-10-04'))->modify('monday this week')->format('Y-m-d'), PHP_EOL;
2026-09-28〜2026-10-04
2026-09-28
monday this week は、日曜日(10月4日)に実行しても同じ週の月曜日(9月28日)を返しました。PHPでは週の始まりが月曜日として扱われます。
曜日を日本語で表示する
date('D') や date('l') は英語で返るため、日本語にするには配列を使う方法と、intl拡張の IntlDateFormatter を使う方法があります。
配列を使う方法(拡張モジュールなしで動く)
$w = ['日', '月', '火', '水', '木', '金', '土'];
$d = new DateTimeImmutable('2026-10-02');
echo $d->format('Y年n月j日') . '(' . $w[(int)$d->format('w')] . ')', PHP_EOL;
$ts = strtotime('2026-10-04');
echo date('n/j', $ts) . '(' . $w[date('w', $ts)] . ')', PHP_EOL;
2026年10月2日(金)
10/4(日)
w は日曜を 0 とする番号なので、配列は「日」から始めます。
IntlDateFormatterを使う方法
$f = new IntlDateFormatter('ja_JP', IntlDateFormatter::FULL, IntlDateFormatter::NONE, 'Asia/Tokyo');
echo $f->format($d), PHP_EOL;
$f = new IntlDateFormatter('ja_JP', IntlDateFormatter::NONE, IntlDateFormatter::NONE, 'Asia/Tokyo', null, 'y年M月d日(E) HH:mm');
echo $f->format(new DateTimeImmutable('2026-10-02 14:05')), PHP_EOL;
$f->setPattern('EEEE');
echo $f->format($d), PHP_EOL;
2026年10月2日金曜日
2026年10月2日(金) 14:05
金曜日
IntlDateFormatter のパターン文字は date() とは別の体系(ICUの書式)で、E が曜日の短い形、EEEE が長い形です。日付・時刻のスタイル定数ごとの出力は次のとおりでした(2026-10-02 14:05:09 を日付・時刻とも同じスタイルで整形)。
| スタイル | 出力 |
|---|---|
FULL |
2026年10月2日金曜日 14時05分09秒 日本標準時 |
LONG |
2026年10月2日 14:05:09 JST |
MEDIUM |
2026/10/02 14:05:09 |
SHORT |
2026/10/02 14:05 |
和暦(令和・平成)で表示する
intl拡張が使える環境では、ロケールに @calendar=japanese を付け、カレンダーに IntlDateFormatter::TRADITIONAL を指定すると和暦で表示できます。
$wa = new IntlDateFormatter(
'ja_JP@calendar=japanese',
IntlDateFormatter::FULL,
IntlDateFormatter::NONE,
'Asia/Tokyo',
IntlDateFormatter::TRADITIONAL
);
foreach (['2026-10-02', '2019-04-30', '2019-05-01', '1989-01-07', '1989-01-08'] as $s) {
echo $s, "\t", $wa->format(new DateTimeImmutable($s)), PHP_EOL;
}
2026-10-02 令和8年10月2日金曜日
2019-04-30 平成31年4月30日火曜日
2019-05-01 令和元年5月1日水曜日
1989-01-07 昭和64年1月7日土曜日
1989-01-08 平成元年1月8日日曜日
元号の切り替わり日(2019年5月1日、1989年1月8日)も正しく判定され、1年目は「元年」と表示されました。パターンを自分で指定する場合は G が元号、y が年です。
$wa2 = new IntlDateFormatter('ja_JP@calendar=japanese', IntlDateFormatter::NONE, IntlDateFormatter::NONE,
'Asia/Tokyo', IntlDateFormatter::TRADITIONAL, 'Gy年M月d日');
echo $wa2->format(new DateTimeImmutable('2026-10-02')), ' / ', $wa2->format(new DateTimeImmutable('2019-05-01')), PHP_EOL;
$wa2->setPattern('GGGGGy.MM.dd');
echo $wa2->format(new DateTimeImmutable('2026-10-02')), PHP_EOL;
令和8年10月2日 / 令和1年5月1日
R8.10.02
独自パターン Gy年 では1年目が「令和1年」になりました。 「元年」と表示したい場合は、FULL や LONG のスタイルを使います。
intl拡張が使えない環境では、元号の開始日を配列で持つ方法があります。
function wareki(DateTimeInterface $d): string
{
$eras = [['令和', '2019-05-01'], ['平成', '1989-01-08'], ['昭和', '1926-12-25'],
['大正', '1912-07-30'], ['明治', '1868-01-25']];
foreach ($eras as [$name, $start]) {
if ($d->format('Y-m-d') >= $start) {
$y = (int)$d->format('Y') - (int)substr($start, 0, 4) + 1;
return $name . ($y === 1 ? '元' : $y) . '年' . $d->format('n月j日');
}
}
return $d->format('Y年n月j日');
}
foreach (['2026-10-02', '2019-04-30', '2019-05-01', '1989-01-07'] as $s) {
echo wareki(new DateTimeImmutable($s)), PHP_EOL;
}
令和8年10月2日
平成31年4月30日
令和元年5月1日
昭和64年1月7日
タイムゾーンの設定と変換
date_default_timezone_setで既定のタイムゾーンを決める
$ts = 1790902800;
echo date('Y-m-d H:i:s T', $ts), PHP_EOL; // 設定前(この環境の既定は UTC)
date_default_timezone_set('Asia/Tokyo');
echo date('Y-m-d H:i:s T', $ts), PHP_EOL;
2026-10-02 01:00:00 UTC
2026-10-02 10:00:00 JST
同じタイムスタンプでも、表示は9時間違います。タイムスタンプは世界共通の「ある瞬間」を表す数値で、タイムゾーンは「それをどの地域の時計で読むか」の設定です。
| 設定する場所 | 書き方 | 範囲 |
|---|---|---|
php.ini |
date.timezone = Asia/Tokyo |
サーバー全体 |
| スクリプトの先頭 | date_default_timezone_set('Asia/Tokyo'); |
そのスクリプト |
| オブジェクトごと | new DateTimeImmutable('now', new DateTimeZone('Asia/Tokyo')) |
そのオブジェクトだけ |
タイムゾーン名のつづりが違うと、date_default_timezone_set() は false を返し、次の通知が出ました。設定は変更されません。
PHP Notice: date_default_timezone_set(): Timezone ID 'Asia/Tokio' is invalid
別のタイムゾーンに変換する
$tokyo = new DateTimeImmutable('2026-10-02 09:00:00', new DateTimeZone('Asia/Tokyo'));
echo $tokyo->format('c'), PHP_EOL;
echo $tokyo->setTimezone(new DateTimeZone('UTC'))->format('c'), PHP_EOL;
echo $tokyo->setTimezone(new DateTimeZone('America/New_York'))->format('Y-m-d H:i T (P)'), PHP_EOL;
echo $tokyo->setTimezone(new DateTimeZone('Europe/London'))->format('Y-m-d H:i T (P)'), PHP_EOL;
var_dump($tokyo->getTimestamp() === $tokyo->setTimezone(new DateTimeZone('UTC'))->getTimestamp());
2026-10-02T09:00:00+09:00
2026-10-02T00:00:00+00:00
2026-10-01 20:00 EDT (-04:00)
2026-10-02 01:00 BST (+01:00)
bool(true)
setTimezone() は表示するタイムゾーンを切り替えるだけで、指している瞬間(タイムスタンプ)は変わりません。 サマータイム(EDT、BST)も自動で反映されています。
UTCで保存された日時を日本時間で表示する例です。
$utc = new DateTimeImmutable('2026-10-01T15:30:00Z');
echo $utc->setTimezone(new DateTimeZone('Asia/Tokyo'))->format('Y-m-d H:i:s'), PHP_EOL;
$fromTs = new DateTimeImmutable('@1790902800'); // @つきはタイムスタンプ。常にUTCになる
echo $fromTs->format('c'), ' -> ', $fromTs->setTimezone(new DateTimeZone('Asia/Tokyo'))->format('c'), PHP_EOL;
2026-10-02 00:30:00
2026-10-02T01:00:00+00:00 -> 2026-10-02T10:00:00+09:00
文字列の末尾に Z や +09:00 があるとき、また @タイムスタンプ で作ったときは、既定のタイムゾーンではなくその指定が使われます。 表示前に setTimezone() で日本時間に切り替えましょう。
文字列を日付として読み取る・検証する
createFromFormatで書式を指定して読み取る
echo DateTimeImmutable::createFromFormat('!Y/m/d', '2026/10/02')->format('Y-m-d H:i:s'), PHP_EOL;
echo DateTimeImmutable::createFromFormat('Y年n月j日 H:i', '2026年10月2日 14:05')->format('c'), PHP_EOL;
var_dump(DateTimeImmutable::createFromFormat('Y-m-d', '2026/10/02'));
2026-10-02 00:00:00
2026-10-02T14:05:00+09:00
bool(false)
書式の先頭に ! を付けると、指定しなかった時刻が 00:00:00 になります。 ! を付けない場合は、時刻に現在の時刻が入ります。書式と文字列が合わないときは false が返ります。
入力された日付が正しいかを確かめる
createFromFormat() も存在しない日付を繰り上げるため、読み取った結果を同じ書式で整形し直し、元の文字列と一致するかで判定します。
function isValidDate(string $s, string $fmt = 'Y-m-d'): bool
{
$d = DateTimeImmutable::createFromFormat('!' . $fmt, $s);
return $d !== false && $d->format($fmt) === $s;
}
var_dump(isValidDate('2026-02-28'), isValidDate('2026-02-30'), isValidDate('2026-2-3'), isValidDate('abc'));
bool(true)
bool(false)
bool(false)
bool(false)
読み取れない文字列を渡したとき
try {
new DateTimeImmutable('abc');
} catch (Throwable $e) {
echo get_class($e), ': ', $e->getMessage(), PHP_EOL;
}
DateMalformedStringException: Failed to parse time string (abc) at position 0 (a): The timezone could not be found in the database
PHP 8.4 では DateMalformedStringException が投げられました。modify('abc') も同じ例外になります。利用者の入力をそのまま渡す場合は、try〜catch で受けるか、先に isValidDate() のような関数で確かめます。
日付処理のチェックリスト
| 確認項目 | 内容 |
|---|---|
| タイムゾーンを指定している | php.ini の date.timezone か date_default_timezone_set('Asia/Tokyo') |
分は i、月は m |
H:i:s と Y-m-d |
新しいコードは DateTimeImmutable |
元の値が変わらない。戻り値を必ず受け取る |
月単位の計算は first day of を使う |
31日に +1 month すると翌々月になることがある |
通算日数は days |
d は月を除いた残りの日数 |
strtotime() の戻り値を確認する |
読み取れないと false(1970年1月1日と表示される) |
入力の検証は checkdate() か整形し直して比較 |
2月30日は3月2日に繰り上がる |
| APIや保存にはタイムゾーンつきの形 | c や DateTimeInterface::ATOM |
よくある質問
Q. date() と DateTime はどちらを使えばよいですか?
A. 現在の日時を表示するだけなら date('Y-m-d H:i:s') が手軽です。日付の足し引き、差の計算、タイムゾーンの変換を行う場合は DateTimeImmutable を使うと、元の値が変わらず読みやすく書けます。フォーマット文字はどちらも共通です。
Q. 日付が1970年1月1日と表示されるのはなぜですか?
A. date() の第2引数に 0 や false が渡っています。多くは strtotime() が文字列を読み取れずに false を返したケースです。strtotime() の戻り値を var_dump() で確認してみてください。
Q. 時刻が9時間ずれるのはなぜですか?
A. PHPの既定のタイムゾーンが UTC になっています。php.ini に date.timezone = Asia/Tokyo を設定するか、スクリプトの先頭で date_default_timezone_set('Asia/Tokyo'); を呼び出します。
Q. 来月の同じ日を求めるにはどうすればよいですか?
A. 28日までの日付なら modify('+1 month') でそのまま求められます。29〜31日は翌月にその日がない場合があるので、本文の addMonths() のように「翌月の月末を上限にする」処理を入れます。月初・月末が欲しいだけなら first day of next month・last day of next month が使えます。
まとめ
date('Y-m-d H:i:s')が基本形。月はm、分はi、ゼロなしはn・j、月末日はt- フォーマット文字は
date()とDateTime::format()で共通。ミリ秒v・マイクロ秒uはクラスで使う strtotime()は相対表現(+1 week、next monday、last day of this month)を読み取れる。読み取れないときはfalseDateTimeは計算で元の値が変わり、DateTimeImmutableは新しいオブジェクトを返す。新しいコードは後者がおすすめ- 1月31日の
+1 monthは3月3日になる。月単位の計算はfirst day of・last day ofか、月末を上限にする関数で行う - 日数差は
diff()->days、曜日の日本語は配列かIntlDateFormatter、和暦はja_JP@calendar=japanese - タイムゾーンは最初に設定し、変換は
setTimezone()で行う
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「PHP date関数フォーマット一覧|DateTimeでの日付計算も解説」
株式会社RJCでは、日付や時刻の扱い方といった基礎を仲間と学び合っています。こうした知識を共有しながら、日々技術を磨いています。
株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。
WE ARE HIRING
RJCで一緒に開発しながら、
成長を楽しみませんか?
RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!
- 127日年間休日
- 12時間平均残業時間
- 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!
ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。