web-dev-qa-db-ja.com

'c'タイムフォーマットを使用すると、時間関数に無効なタイムゾーンが表示されるのはなぜですか?

これらは私が私のテーマの中で記事の Published last modified datesを含む "entry-meta"を表示するために使う関数です:

// Shows Author and Published Date
if ( ! function_exists( 'reddle_posted_on' ) ) :
function reddle_posted_on() {
    printf( __( '<span class="byline">Posted by <span class="author vcard"><a class="url fn n" href="%5$s" title="%6$s" rel="author">%7$s</a></span></span><span class="sep"> &mdash; </span><span class="entry-date"><time datetime="%3$s" pubdate>%4$s</time></span>', 'reddle' ),
        esc_url( get_permalink() ),
        esc_attr( get_the_time() ),
        esc_attr( get_the_date( 'c' ) ),
        esc_html( get_the_date() ),
        esc_url( get_author_posts_url( get_the_author_meta( 'ID' ) ) ),
        sprintf( esc_attr__( 'View all posts by %s', 'the-wolf' ), get_the_author() ),
        esc_html( get_the_author() )
    );
}
endif;

// Shows Last Modified Date
if ( ! function_exists( 'reddle_last_modified_on' ) ) :
function reddle_last_modified_on() {
    printf( __( 'Last updated on <time class="updated" itemprop="dateModified" datetime="%2$s">%3$s</time>', 'reddle' ),
        esc_attr( get_the_modified_time() ),
        esc_attr( get_the_modified_date( 'c' ) ),
        esc_html( get_the_modified_date( 'F j, Y ~ H:i' ) )
    );
}
endif;

これらの機能に何か問題がありますか?問題は、 WordPress Dashboard>設定>一般 で私のブログのタイムゾーンをGMT-05:00(-04:00 DST)に設定しているにもかかわらず、出力されるタイムスタンプがGMT+00:00を示すことです。何かアイディアは?

3
its_me

問題は、正しい出力のためにWPが date_i18n() 関数で日付を処理する必要があることです。日付形式を使用する場合、PHPコードにハードコードされている(PHP DATE_*定数に保存されていない)'c'のように-あなたのコードでは利用できないため、WP プロセスへ。

システム全体の修正は、can WPコードによってアクセスされる類似の形式で日付を再処理することです。

add_filter( 'date_i18n', 'fix_c_time_format', 10, 4 );

function fix_c_time_format( $date, $format, $timestamp, $gmt ) {

    if ( 'c' == $format )
        $date = date_i18n( DATE_ISO8601, $timestamp, $gmt );

    return $date;
}
4
Rarst

WordPressは自動的にPHPのサーバーのタイムゾーンをGMTに設定します。これは、日付操作の一貫性を保つためのものです。変更すると、エラーが発生する可能性があります。

これは、dateのようなネイティブ関数はすべての日付をGMT(またはUTC)形式であると解釈することを意味します。同様に、DateTimeオブジェクトのタイムゾーンはUTCです。

意図しない結果になる可能性があるため、実際にはこれを変更しないでください。

問題

get_the_modified_date( 'c' )を使うことの問題は、取得する日時(say 2012-06-14 11:55:00 )がブログのタイムゾーンの変更された日付を参照することです。日付が 'c'を使用してフォーマットされている場合 - 上記の日時はUTCタイムゾーンにあると想定されます。

( 'c'とは異なり)タイムゾーンを含まないフォーマットを使用している場合は、問題ありません。 _(ところで、unixタイムスタンプは暗黙的にタイムゾーンを参照します)。

WordPressで日付を表示する方法

UTCタイムゾーンのすべての日付を処理してから表示する場合に限り、それらを現地のタイムゾーンに変換することをお勧めします。

ソリューション

代わりにget_the_modified_date( 'c', true )は、取得した日時が実際にはGMT(UTC)タイムゾーンで変更された日付であることを保証します。これが 'c'を使用して形成されると、日時はUTCタイムゾーン内にあると再び仮定されます(しかし今では正しくそうです)。

異なるタイムゾーンを使用する

あなたは、PHPのタイムゾーンをあなたのブログのタイムゾーンに設定してから、また戻ることができます。しかし、これは素晴らしいことではありません。代わりに、PHPのDateTimeオブジェクトを利用してください。 PHP datetimeオブジェクトはタイムゾーンをUTCに設定しますが、これはオブジェクトの構築で明示的に上書きすることができます。

$timestamp = get_the_modified_date( 'u', true );

//Correct date-time object in UTC
$date_obj = new DateTime("@$timestamp"); 

//Displays 2012-06-14T14:32:11-00:00
echo $date_obj->format('c');

//Correct date-time object now in America/New_York timezone
$date_obj->setTimezone(new DateTimeZone('America/New_York'));

//Displays 2012-06-14T10:32:11-04:00
echo $date_obj->format('c');

ブログのタイムゾーンのPHP DateTimeZoneオブジェクトの後ろにいる場合は、この要旨を参照してください。 https://Gist.github.com/2724520

2
Stephen Harris

(決して考えないで、上記のより良い答えに従ってください。この答えを編集しないでください。これは参考として存在します。)

状況

ほとんどのWordPressテーマとプラグイン(特に尊敬される開発者によるもの)はタイムスタンプをこれと同じフォーマットで出力するc定数を使用します:2012-06-14T10:32:11-00:00

例えば、<?php get_the_date( 'c' ) ?>はこの2012-06-14T10:32:11-00:00のような何かを出力します。

当初、私はこれは全員考え抜かれた決断だと思いましたが、それからそれはタイムスタンプフォーマット World Wide Webコンソーシアムが推奨 _であり、独自の定義済み日付定数DATE_W3Cを持っています。質問はもうありません、期間。

WordPressの問題

たとえば、WordPressダッシュボード>設定>一般で、タイムゾーンNew Yorkに設定したとします。

さて、テンプレート内のこのコード<?php get_the_date( 'c' ) ?>(前述のテーマやプラグイン)はこのようなものを出力するでしょう:2012-06-14T10:32:11-00:00

間違いを見て?ええ、それがこの2012-06-14T10:32:11-04:00であるべきなら、WordPressはこの2012-06-14T10:32:11-00:00を出力します

これは、WordPressのコア開発者によって開発されたテーマやプラグインでも同じです。

日付と時刻は、America/New_Yorkというタイムゾーンに対して絶対的に正しいです。しかし、タイムゾーンオフセット、すなわちGMT/UTCとの差はNOTです。それは小さな問題ではありません、それは間違った時です!

ソリューション

最初、私はget_the_date( 'c' );get_the_modified_date( 'c' );のすべてのインスタンスをそれぞれget_the_date( 'Y-m-d\TH:i:sP' );get_the_modified_date( 'Y-m-d\TH:i:sP' );に変更しました、そしてそれは問題を解決したように見えました(すなわち、正しいオフセットを示すこと)。

本当の問題は、私が使用するいくつかのプラグインにこれ​​らの変更を加えなければならないことに気付いたときです(はい、それらはタイムスタンプを出力します、例えば Facebook plugin's open graph機能)。これは実行可能ではありません。それで、私は代替案を探し始めました。

日付のためのPHP手動関数リファレンスの例 のおかげで、I はおそらく WordPressのTimezone設定をこのような関数で上書きできることに気づきました.php(最初の<?phpの直後):

date_default_timezone_set('America/New_York');

そして、やあ! get_the_date( 'c' );get_the_modified_date( 'c' );は、正しい日付、時刻、タイムゾーンオフセットを表示し始めました。それらすべてを統治するための一つの変更!

その他のリンク


事前編集

cの代わりにY-m-d\TH:i:sPを使用します - タイムスタンプのフォーマットは変わりませんが、正しいタイムゾーンオフセットが表示されます。

この PHP Date()Cheatsheat は非常に役に立ちました。

2
its_me