2026年8月17日
2026年8月17日
WordPressでPHPのタイムゾーンずれが原因のスケジュール不具合を修正する方法
予約投稿や定期処理が9時間ずれる、表示される時刻が日本時間にならない、といった不具合の多くは「WordPressの時刻はUTCで計算し、表示のときだけサイトのタイムゾーンに直す」という前提を崩しているコードや設定が原因です。この記事では、ずれの正体を確認する手順と、設定・コードそれぞれの直し方を、確認方法つきで説明します。
まず知っておきたいWordPressの時刻の扱い
WordPressは読み込みの途中で、PHPのデフォルトタイムゾーンを UTC に固定します(wp-settings.php 内の date_default_timezone_set( 'UTC' ))。そのうえで、管理画面の「設定 > 一般」にあるタイムゾーン設定を使い、表示用の時刻だけを変換します。
この設定は2つのオプションに保存されます。
timezone_string… 「東京」のような都市を選んだときの値(例:Asia/Tokyo)gmt_offset… 「UTC+9」のようにオフセットを直接選んだときの数値
都市名で選ぶと夏時間のある地域でも自動で切り替わるため、基本は都市名を選ぶのがおすすめです。投稿にも post_date(サイトの現地時刻)と post_date_gmt(UTC)の2つの日時があり、予約投稿のcronイベントはUTC側の値をもとに登録されます。
つまり「PHPはUTC、表示はサイト設定」が正しい状態です。php.ini の date.timezone を Asia/Tokyo にしても、WordPressの処理中はUTCに上書きされるため、php.ini を変えるだけでは直りません。
ずれの原因を特定する手順
作業前にバックアップを取り、可能ならステージング環境で確認してください。
1. サイトヘルスを確認する
「ツール > サイトヘルス」を開き、PHPのデフォルトタイムゾーンに関する警告が出ていないかを見ます。WordPress 5.3以降には、読み込み後に date_default_timezone_set() でタイムゾーンが変更されたことを検出するチェックがあります(表示文言はバージョンにより異なります)。この警告が出ていれば、どこかのプラグインやテーマが原因である可能性が高いです。
2. 設定値と実際の時刻を出してみる
WP-CLIが使える環境なら、次のコマンドで設定とPHPの状態をまとめて確認できます。
wp option get timezone_string
wp option get gmt_offset
wp eval 'echo date_default_timezone_get(), PHP_EOL, wp_date( "Y-m-d H:i:s T" ), PHP_EOL, gmdate( "Y-m-d H:i:s" ), " UTC", PHP_EOL;'
1行目のPHPタイムゾーンが UTC 以外なら、プラグインかテーマが書き換えています。wp_date() の結果がサイトの現地時刻、gmdate() の結果がUTCになっていれば、WordPress本体の計算は正常です。timezone_string が空で gmt_offset が0のままなら、そもそも設定が「UTC+0」になっています。
3. タイムゾーンを書き換えているコードを探す
サーバーにSSHで入れる場合は、次のように検索します。
grep -rn "date_default_timezone_set" wp-content/plugins wp-content/themes wp-content/mu-plugins
見つかったファイルの持ち主(プラグインやテーマ)を特定し、更新版で直っていないか、設定で無効にできないかを確認します。自作テーマやfunctions.phpに書いてある場合は削除して、後述の正しい書き方に置き換えます。
4. cronイベントの登録時刻を見る
wp cron event list --fields=hook,next_run_gmt,recurrence
next_run_gmt はUTCで表示されます。たとえば「毎日午前3時(日本時間)」のつもりのイベントなら、UTCでは前日の18時になっているはずです。ここが日本時間の3時のまま(=UTCで3時)になっていれば、登録時の計算が9時間ずれています。
症状別の原因と直し方
表示される時刻が9時間ずれる
テンプレートやショートコードでPHPの date() を使っていると、WordPress上ではUTCの時刻が出ます。表示には wp_date() を使います。投稿日なら get_the_date() や get_the_time() がサイト設定に従った値を返します。
// NG: WordPress上ではUTCの時刻になる
echo esc_html( date( 'Y-m-d H:i' ) );
// OK: サイトのタイムゾーンで表示する
echo esc_html( wp_date( 'Y-m-d H:i' ) );
定期処理(wp_schedule_event)の実行時刻がずれる
wp_schedule_event() の第1引数は、UTC基準のUnixタイムスタンプです。ここに current_time( 'timestamp' ) の値を渡すと、オフセット分を足した「見かけの時刻」になるため、日本では9時間遅れて実行されます。current_time( 'timestamp' ) は公式ドキュメントでも本来のUnixタイムスタンプではないと説明されており、新しいコードでは使わないのが無難です。
サイトの現地時刻で「毎日3時」を指定したい場合は、wp_timezone() を使って日時オブジェクトを作り、そこからタイムスタンプを取り出します。functions.php ではなく、mu-plugin や自作プラグインに置く例です。
<?php
// wp-content/mu-plugins/myprefix-daily-job.php
add_action( 'init', function () {
if ( wp_next_scheduled( 'myprefix_daily_job' ) ) {
return;
}
$tz = wp_timezone(); // サイト設定のタイムゾーン
$next = new DateTimeImmutable( 'today 03:00', $tz ); // 今日の3時(現地時刻)
if ( $next <= current_datetime() ) {
$next = $next->modify( '+1 day' ); // 過ぎていれば翌日の3時
}
wp_schedule_event( $next->getTimestamp(), 'daily', 'myprefix_daily_job' );
} );
add_action( 'myprefix_daily_job', function () {
$now = current_datetime(); // サイトのタイムゾーンの DateTimeImmutable
error_log( 'myprefix_daily_job: ' . $now->format( 'Y-m-d H:i:s T' ) );
} );
すでにずれた時刻で登録されたイベントは、上のコードを入れても自動では直りません。wp cron event delete myprefix_daily_job などで一度削除し、再登録させます。なお daily は単純に86400秒ごとなので、夏時間のある地域では現地時刻が1時間ずれる時期があります。
予約投稿の時刻がおかしい
予約投稿を登録したときにタイムゾーン設定が誤っていた場合、その投稿の post_date_gmt とcronイベントは誤った時刻のまま残ります。設定を直したあと、該当する予約投稿を開いて日時を確認し、保存し直してください。
なお「予約投稿の失敗」と表示されて公開されない場合は、時刻のずれではなくWP-Cronそのものが動いていないことが多いです。サイトへのアクセスが少ない、DISABLE_WP_CRON が設定されている、ループバック通信が失敗している、などを先に確認します。
独自SQLで日付の絞り込みがずれる
$wpdb で直接クエリを書くとき、post_date とMySQLの NOW() を比べると、MySQLのセッションのタイムゾーン次第でずれます。比較はUTC同士にそろえ、post_date_gmt を使うと安定します。値は $wpdb->prepare() で渡します。
global $wpdb;
$since = gmdate( 'Y-m-d H:i:s', time() - DAY_IN_SECONDS ); // 24時間前(UTC)
$ids = $wpdb->get_col(
$wpdb->prepare(
"SELECT ID FROM {$wpdb->posts} WHERE post_status = 'publish' AND post_date_gmt >= %s",
$since
)
);
サーバーのcronやPHPスクリプトがずれる
OSのcrontabに書いた時刻は、サーバーのタイムゾーンで解釈されます。timedatectl などでサーバーの設定を確認し、crontabの時刻をどちらの基準で書いているのかを決めておきます。WordPressを読み込まない単独のPHPスクリプトでは php.ini の date.timezone が効くので、こちらは php.ini 側で指定します。
直したあとの確認
修正後は、次の点を順に見ておくと再発に気づきやすくなります。いずれも現行のWordPressで使える確認方法です(2026年10月現在)。
- サイトヘルスのタイムゾーン警告が消えている
wp evalでdate_default_timezone_get()がUTCを返すwp cron event listのnext_run_gmtが、意図した現地時刻をUTCに直した値になっている- テスト用の予約投稿を数分後に設定し、時刻どおりに公開される
まとめ
- WordPressはPHPのタイムゾーンをUTCに固定し、表示だけサイト設定で変換する。
date_default_timezone_set()で書き換えるコードが不具合の主な原因になる - タイムゾーンは「設定 > 一般」で都市名を選ぶ。設定値は
timezone_stringとgmt_offsetで確認できる - 表示は
wp_date()、現在時刻のオブジェクトはcurrent_datetime()、スケジュール登録はwp_timezone()から作ったUTCタイムスタンプを使う - ずれた時刻で登録済みのcronイベントや予約投稿は、修正後に登録し直す
- 公開されない予約投稿は、時刻ではなくWP-Cronの停止が原因のことも多い