WordPressでstrtotimeとかmktimeしたり、日付を扱うときの注意事項

WordPressでカスタムフィールドを使って日付を入力させたりする、なんてことはよくある話だと思います。

ただしWordPressでは、wp-settings.phpで以下のコードが実行されて、タイムゾーンがUTCに変更されます。

date_default_timezone_set( 'UTC' );

なので、PHPのtimezoneの設定がどうなっていようと、UTCになってしまいます。なので、unixtime等を扱うときはかなり注意が必要だったりします。

対処法

その1 時差分を追加

get_option('gmt_offset')で、WordPressで設定されているUTCとの時差が取得できますので、それをmktimeや、strtotimeの返却する値に追加します。

<?php
function local_mktime() {
 $defaults = array(
 date("H"),
 date("i"),
 date("s"),
 date("n"),
 date("j"),
 date("Y"),
 -1,
 );
 $args = func_get_args();
 $param = array_merge( $defaults, $args );
 $offset = get_option('gmt_offset') * 60 * 60;
 return mktime( $param[0], $param[1], $param[2], $param[3], $param[4], $param[5], $param[6]) + $offset;
}

function local_strtotime( $time, $now = null ) {
 $offset = get_option('gmt_offset') * 60 * 60;
 if( $now == null ) {
 $now = time();
 }
 
 return strtotime( $time, $now ) + $offset; 
}

その2 一時的にタイムゾーンを変更する

date_default_timezone_get()で現在のタイムゾーンを取得、date_default_timezone_set( $timezone )で、タイムゾーンを変更できます。なので、これを使って、一時的にタイムゾーンを変更できます。

<?php
function local_mktime() {
 $defaults = array(
 date("H"),
 date("i"),
 date("s"),
 date("n"),
 date("j"),
 date("Y"),
 -1,
 );
 $args = func_get_args();
 $param = array_merge( $defaults, $args );

 $internal_timezone = date_default_timezone_get();
 date_default_timezone_set( 'Asia/Tokyo' );

 $timestamp = mktime( $param[0], $param[1], $param[2], $param[3], $param[4], $param[5], $param[6]);

 date_default_timezone_set( $internal_timezone );

 return $timestamp;
}

function local_strtotime( $time, $now = null ) {
 $offset = get_option('gmt_offset') * 60 * 60;
 if( $now == null ) {
 $now = time();
 }

 $internal_timezone = date_default_timezone_get();
 date_default_timezone_set( 'Asia/Tokyo' );

 $timestamp = strtotime( $time, $now ); 

 date_default_timezone_set( $internal_timezone );

 return $timestamp;

}

時差の絡んだ日付の変換はかなりややこしいです。timestampにする必要が無いところはstr_replace等で数値文字列に変換して対処する等する方が、バグなどを埋め込まずに済みそうです。