PHP のタイムゾーン - DateTimeZone で時差を扱う

サーバーとユーザーが異なる国にいる場合や、複数の拠点の時刻を同時に扱う場合、タイムゾーンの管理は避けて通れません。PHP では DateTimeZone クラスがタイムゾーンの情報を保持し、DateTime と組み合わせることで時差を意識した日時処理を実現します。

DateTimeZone オブジェクトの生成

コンストラクタにタイムゾーン識別子を渡してオブジェクトを生成します。

$tz = new DateTimeZone('Asia/Tokyo');
echo $tz->getName();
// Asia/Tokyo

識別子は IANA タイムゾーンデータベースに準拠しており、「地域/都市名」の形式で指定するのが一般的です。「JST」のような略称も一部は使えますが、曖昧さを避けるために地域/都市名の形式が推奨されています。

よく使うタイムゾーン識別子

識別子UTC との差地域
Asia/Tokyo+09:00日本
America/New_York-05:00米国東部
Europe/London+00:00イギリス
識別子UTC との差地域
Asia/Shanghai+08:00中国
America/Los_Angeles-08:00米国西部
Europe/Berlin+01:00ドイツ

UTC との差は標準時のものであり、夏時間(DST)が適用される地域では期間中にオフセットが変わります。DateTimeZone はこの夏時間の切り替えも内部で管理しているため、開発者が手動で計算する必要はありません。

DateTime と組み合わせる

DateTimeZone は単体で使うというよりも、DateTime のコンストラクタや setTimezone メソッドに渡して使うのが基本的な使い方です。

$tokyo = new DateTime('2025-07-01 12:00:00', new DateTimeZone('Asia/Tokyo'));
$ny    = new DateTime('2025-07-01 12:00:00', new DateTimeZone('America/New_York'));

echo $tokyo->format('Y-m-d H:i:s P');
// 2025-07-01 12:00:00 +09:00

echo $ny->format('Y-m-d H:i:s P');
// 2025-07-01 12:00:00 -04:00

同じ「12:00:00」でもタイムゾーンが異なれば、表す瞬間はまったく別のものになります。ニューヨークの -04:00 は夏時間が適用された結果であり、標準時の -05:00 とは異なっている点にも注目してください。

setTimezone でタイムゾーンを変換する

既存の DateTime オブジェクトのタイムゾーンを変換するには setTimezone メソッドを使います。

$dt = new DateTime('2025-07-01 12:00:00', new DateTimeZone('Asia/Tokyo'));
echo $dt->format('Y-m-d H:i:s T');
// 2025-07-01 12:00:00 JST

$dt->setTimezone(new DateTimeZone('America/New_York'));
echo $dt->format('Y-m-d H:i:s T');
// 2025-06-30 23:00:00 EDT

日本時間の 7 月 1 日 12:00 は、ニューヨーク時間では前日の 23:00 に相当します。setTimezone は内部のタイムスタンプを変えずに表示上のタイムゾーンだけを切り替えるため、同じ瞬間を異なるタイムゾーンで表現できる仕組みです。

getOffset で UTC からの秒数差を取得する

DateTimeZone の getOffset メソッドは、指定した日時における UTC からのオフセットを秒数で返します。

$tz = new DateTimeZone('Asia/Tokyo');
$dt = new DateTime('2025-07-01', $tz);
echo $tz->getOffset($dt);
// 32400(9時間 × 3600秒)

getOffset の引数に DateTime オブジェクトを渡す必要があるのは、夏時間の有無によってオフセットが変わるためです。

たとえば America/New_York は標準時で -18000(-5 時間)、夏時間で -14400(-4 時間)を返す。どの時点のオフセットかを特定するために日時が必要になる。

$tz = new DateTimeZone('America/New_York');

$winter = new DateTime('2025-01-15', $tz);
echo $tz->getOffset($winter); // -18000(-5時間)

$summer = new DateTime('2025-07-15', $tz);
echo $tz->getOffset($summer); // -14400(-4時間)

getTransitions で夏時間の切り替え情報を取得する

getTransitions メソッドは、タイムゾーンのオフセットが切り替わるタイミングの一覧を返します。

$tz = new DateTimeZone('America/New_York');
$transitions = $tz->getTransitions(
    strtotime('2025-01-01'),
    strtotime('2025-12-31')
);

foreach ($transitions as $tr) {
    echo $tr['time'] . ' → ' . ($tr['isdst'] ? 'DST' : 'STD') . "\n";
}

夏時間がいつ始まっていつ終わるかを調べたい場合や、特定の期間にオフセットの変更があるかを事前に確認したい場合に使えます。

listIdentifiers で利用可能なタイムゾーン一覧を取得する

DateTimeZone::listIdentifiers は、PHP が認識しているすべてのタイムゾーン識別子を配列で返す静的メソッドです。

$all = DateTimeZone::listIdentifiers();
echo count($all);
// 例: 425

// アジア地域だけを取得
$asia = DateTimeZone::listIdentifiers(DateTimeZone::ASIA);
foreach (array_slice($asia, 0, 5) as $id) {
    echo $id . "\n";
}
// Asia/Aden
// Asia/Almaty
// Asia/Amman
// Asia/Anadyr
// Asia/Aqtau

引数に DateTimeZone::ASIA や DateTimeZone::EUROPE などの定数を渡すと、特定の地域に絞り込めます。ユーザーにタイムゾーンを選択させるフォームを構築するときに便利です。

date_default_timezone_set でデフォルトを設定する

PHP スクリプト全体のデフォルトタイムゾーンを設定するには date_default_timezone_set 関数を使います。

date_default_timezone_set('Asia/Tokyo');

echo date('Y-m-d H:i:s T');
// 例: 2025-07-01 12:00:00 JST

$dt = new DateTime();
echo $dt->getTimezone()->getName();
// Asia/Tokyo

この関数を呼ぶと、date 関数や DateTime コンストラクタ(タイムゾーン未指定時)がすべてこのタイムゾーンを基準に動作します。php.ini の date.timezone ディレクティブでも同じ設定が可能ですが、コード側で明示的に指定しておくとサーバー環境に依存しなくなります。

php.ini で設定

date.timezone = “Asia/Tokyo” と記述する。サーバー全体に適用されるため、すべてのスクリプトに影響する。

コードで設定

date_default_timezone_set(‘Asia/Tokyo’) をスクリプトの先頭で呼ぶ。アプリケーション単位で管理でき、環境差異を吸収しやすい。

デフォルトタイムゾーンが未設定のまま date 関数や DateTime を使うと、PHP が警告を出力します。本番環境では必ずいずれかの方法で設定しておく必要があります。