WordPress のタイムゾーンは UTC に設定されていて、変更不可です。時間がずれてしまう原因はこれです。WordPress のタイムゾーンを無理矢理に変更することはできますが、どのような不具合が起きるか分からないため推奨されません。本稿は WordPress 的にお行儀が良い、ずれない日付の扱い方をまとめています。
WordPress に日付を扱う PHP コードを追加してカスタマイズする場合、まずは WordPress のタイムゾーンと、管理画面で設定できるブログのタイムゾーン(※)の 2つが別々に存在することを認識する必要があります。(※WordPress で構築したサイト上のタイムゾーンです。便宜上「ブログのタイムゾーン」と表記します)
WordPress で日付を扱う関数
WordPress では、多くの場合 PHP の date および time、strtotime はそのまま使えません。基本的には、WordPress で用意されている current_time() または get_date_from_gmt() と組み合わせたり代替します。
尚、検索すると date_i18n() の情報が多いですが、少し古いと思います。current_time() が日付書式文字列を受け取れるようになった WordPress 3.9 以降は current_time() がオススメです。date_i18n() は内部で current_time() を呼んでいます。
current_time( $type, $gmt = 0 )
ブログのタイムゾーンにおける日時を取得できます。
current_time( ‘timestamp’ ) は time の代わりに使えます。
引数の $type には、’timestamp’ または ‘mysql’ または日付書式文字列(そのまま date に渡されます)を指定します。
例えば、曜日付きの今日の日付を取得したいときは以下になります。
ブログのタイムゾーンが日本(GMT+9)の場合の例です。
// 日本時間の 2015年 6月 23日 朝 7時に実行した場合 $today = current_time( 'Y-m-d D H:i' ); // 2015-06-23 Tue 07:00
また、現在の日時から一週間後の日時を取得したいときは以下です。
// 日本時間の 2015年 6月 23日 朝 7時に実行した場合 $aweeklater = date( 'Y-m-d D H:i', strtotime( '+7 days', current_time('timestamp') ) ); // 2015-06-30 Tue 07:00
やってしまいそうな間違い #1
// 日本時間の 2015年 6月 23日 朝 7時に実行した場合 $today = date( 'Y-m-d D H:i' ); // 2015-06-22 Mon 22:00 $aweeklater = date( 'Y-m-d D H:i', strtotime( '+7 days' ) ); // 2015-06-29 Mon 22:00
WordPress のタイムゾーンである UTC における現在日時が返るため、ブログのタイムゾーンが日本の場合、意図した結果より 9時間ずれます。
やってしまいそうな間違い #2
current_time() は内部で time に UTC とブログのタイムゾーンとの時差秒数を加減算して date に渡しています。date で使われる PHP のタイムゾーンは、WordPress のタイムゾーンである UTC のままなので注意です。
// 日本時間の 2015年 6月 23日 朝 7時に実行した場合 $today = current_time( 'Y-m-d D H:i T' ); // 2015-06-23 Tue 07:00 UTC
これは奇妙に思えるかも知れませんが、date や time が扱う UNIX タイムスタンプは ある基点からの経過秒数という相対的な値であることを思い出してください。タイムゾーンの変更は基点の変更を意味します。WordPress では基点が UTC に設定されています。基点を変えずにブログのタイムゾーンに合わせるには、UTC との時差に合わせて経過秒数を進めたり戻したりすれば良いことになります。それが current_time() の動作です。
date_i18n( $dateformatstring, $unixtimestamp = false, $gmt = false )
date_i18n() はブログのタイムゾーンにおけるタイムゾーン付きの日時を取得できる関数です。
// 日本時間の 2015年 6月 23日 朝 7時に実行した場合 $today = date_i18n( 'Y-m-d D H:i T' ); // 2015-06-23 火 07:00 JST
曜日の表示もローカライズしてくれるようです。ただ、date_i18n() のソースを見ると わりと泥臭いことをやっているので、current_time() または次項の get_date_from_gmt() を使うのが良いと思います。
関連リンク
- Function Reference/current time « WordPress Codex
- 関数リファレンス/current time – WordPress Codex 日本語版
- WordPress > current_time() | Function | WordPress Developer Resources
- 関数リファレンス/date i18n – WordPress Codex 日本語版
- WordPress > date_i18n() | Function | WordPress Developer Resources
get_date_from_gmt( $string, $format = ‘Y-m-d H:i:s’ )
主に strtotime() の代わりに使えます。
$string に与えたブログ上の日付形式の文字列を、$format で指定した書式で返します。current_time() と違い、ブログのタイムゾーンが正しく反映されます。$format には PHP の日付書式文字列が そのまま使えます。
例えば、ブログ記事の投稿日付を ISO 8601 形式で取得したい場合は以下になります。
ブログのタイムゾーンが日本(GMT+9)の場合の例です。
global $post; var_dump( $post->post_date ); // 2015-06-23 07:00:00 var_dump( $post->post_date_gmt ); // 2015-06-22 22:00:00 $iso8601 = get_date_from_gmt( $post->post_date_gmt, 'c' ); // 2015-06-23T07:00:00+09:00
やってしまいそうな間違い
global $post; var_dump( $post->post_date ); // 2015-06-23 07:00:00 var_dump( $post->post_date_gmt ); // 2015-06-22 22:00:00 $iso8601_bad = date( 'c', strtotime( $post->post_date ) ); // 2015-06-23T07:00:00+00:00 $iso8601_gmt = date( 'c', strtotime( $post->post_date_gmt ) ); // 2015-06-22T22:00:00+00:00
$iso8601_bad は、一見 正しそうに見えますが、タイムゾーンの表示が +00:00 です。ブログのタイムゾーンが日本の場合、意図した結果より 9時間ずれています。
$iso8601_gmt は、日付データとしては正しいですが、タイムゾーンが UTC です。それを意図している場合は問題ありません。
関連リンク
- Function Reference/get date from gmt « WordPress Codex
- WordPress > get_date_from_gmt() | Function | WordPress Developer Resources
まとめ WordPress で日時がずれる場合のベスト プラクティス
- date や time の代わりに current_time() を使う
- strtotime の代わりに get_date_from_gmt() を使う
- タイムゾーンを表示したいときは get_date_from_gmt() または date_i18n() を使う
どなたかのお役に立つことを願いつつ また次回。
Pingback: ズレない!WordPressで現在の日時を取得する方法は current_time を使う
Pingback: ズレない!WordPressで現在の日時を取得する方法は current_time を使う - WordPress Note
Pingback: お気に入り – ブックマーク