web-dev-qa-db-fra.com

Pourquoi les fonctions d'heure affichent-elles un fuseau horaire non valide lors de l'utilisation du format d'heure 'c'?

Ce sont les fonctions que j'utilise dans mon thème pour afficher le "entry-meta" qui inclut publié et dernière modification dates (entre autres) d'un article:

// 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;

Voyez-vous quelque chose de mal avec ces fonctions? Le problème est que, malgré le paramétrage du fuseau horaire de mon blog sur GMT-05:00 (-04: 00 heure d'été) dans Tableau de bord WordPress> Paramètres> Général l'horodatage généré affiche GMT+00:00. Une idée pourquoi?

3
its_me

Le problème est que pour une sortie correcte, WP doit traiter la date via date_i18n() function. Lorsque vous utilisez le format de date, codé en dur dans PHP code (pas simplement enregistré dans PHP DATE_* constant) comme 'c' - il n'est pas disponible pour votre code et donc pour WP à traiter.

Le correctif à l'échelle du système consisterait à re-traiter la date avec un format analogue auquel peut être accédé par WP code:

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 définit automatiquement le fuseau horaire du serveur dans PHP sur GMT. Cela permet de rendre cohérentes les manipulations de date - et si elles sont modifiées, cela peut provoquer des erreurs.

Cela signifie que toute fonction native telle que date interprétera toute date comme étant au format GMT (ou UTC). De même, le fuseau horaire des objets DateTime sera UTC.

Vous ne devriez pas vraiment changer cela, car cela pourrait avoir des conséquences inattendues.

Le problème

Le problème lié à l'utilisation de, par exemple, get_the_modified_date( 'c' ) est que la date/heure qu'il obtient (par exemple, 2012-06-14 11:55:00) fait référence à la date modifiée dans le fuseau horaire du blog. Lorsque la date est formatée à l'aide du "c" - il est supposé que la date-heure ci-dessus est dans le fuseau horaire UTC.

Si vous utilisez un format qui (à la différence de "c") n'inclut pas le fuseau horaire, tout devrait bien se passer. (Un horodatage Unix, en passant, fait implicitement référence à un fuseau horaire).

Comment afficher les dates dans WordPress

Il est recommandé de traiter toutes les dates du fuseau horaire UTC et de les convertir uniquement en les affichant dans votre fuseau horaire local.

La solution

get_the_modified_date( 'c', true ) s'assure plutôt que la date-heure obtenue correspond bien à la date modifiée dans le fuseau horaire GMT (UTC). Maintenant, quand il est formé à l'aide de 'c', il est à nouveau supposé (mais maintenant correctement) que la date-heure est dans le fuseau horaire UTC.

Utiliser un fuseau horaire différent

Vous pouvez définir le fuseau horaire de PHP sur celui de votre blog, puis revenir en arrière. Mais ce n'est pas génial. A la place, utilisez l'objet DateTime de PHP. Le fuseau horaire d'un objet PHP datetime sera défini sur UTC, mais cela peut être explicitement annulé dans la construction de l'objet:

$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');

Si vous êtes après l’objet PHP DateTimeZone du fuseau horaire de votre blog, consultez l’information suivante: https://Gist.github.com/2724520

2
Stephen Harris

(Peu importe, suivez les meilleures réponses ci-dessus. Ne modifiez PAS cette réponse. Elle existe en tant que référence.)}

La situation

La plupart des thèmes et des plugins WordPress (en particulier ceux de développeurs réputés) utilisent la constante c qui génère l'horodatage dans un format identique à celui-ci: 2012-06-14T10:32:11-00:00.

Par exemple, <?php get_the_date( 'c' ) ?> afficherait quelque chose comme ceci 2012-06-14T10:32:11-00:00.

Au départ, je pensais que c’était une décision irréfléchie de la part de tous, mais j’ai ensuite appris qu’il s’agissait d’un format d’horodatage recommandé par le World Wide Web Consortium , et que sa propre date prédéfinie était DATE_W3C. Pas plus de questions, période.

Problèmes dans WordPress

Dites par exemple que dans WordPress Tableau de bord> Paramètres> Général je règle le Fuseau horaire sur New York .

Maintenant, ce code <?php get_the_date( 'c' ) ?> dans un modèle (thèmes ou plugins comme ci-dessus) produirait quelque chose comme ceci: 2012-06-14T10:32:11-00:00

Voyez l'erreur? Oui, quand il DEVRAIT être ce 2012-06-14T10:32:11-04:00/ WordPress génère ce 2012-06-14T10:32:11-00:00

C'est le cas même avec les thèmes et les plugins développés par les développeurs principaux de WordPress.

La date et l’heure sont absolument exactes, par rapport au fuseau horaire qui est America/New_York. Mais le décalage horaire, c’est-à-dire que la différence par rapport à GMT/UTC n’est pas . Ce n'est pas un petit problème, ce n'est pas le moment!

La solution

Au début, j’ai changé toutes les instances de get_the_date( 'c' ); et get_the_modified_date( 'c' ); en get_the_date( 'Y-m-d\TH:i:sP' ); et get_the_modified_date( 'Y-m-d\TH:i:sP' ); respectivement, et cela semblait avoir résolu le problème (c’est-à-dire en montrant le décalage correct).

Le vrai problème, c’est quand j’ai réalisé que je devais apporter ces modifications à quelques plugins que j’utilisais (oui, ils affichent des horodatages, la fonctionnalité de graphe du plugin Facebook open par exemple). Ce n'est pas viable. J'ai donc commencé à chercher des alternatives.

Merci aux exemples de la référence PHP Fonctions manuelles pour Date/Heure , je me suis rendu compte que je pourrait éventuellement remplacer le réglage du fuseau horaire de WordPress par quelque chose comme ceci dans functions.php (juste après le premier <?php):

date_default_timezone_set('America/New_York');

Et le tour est joué! get_the_date( 'c' ); et get_the_modified_date( 'c' ); ont maintenant commencé à afficher la date, l'heure et le décalage horaire corrects! Un changement pour les gouverner tous!

Autres liens


Pré-édition

Utilisez Y-m-d\TH:i:sP au lieu de c - le format d’horodatage reste le même, mais il indique le décalage de fuseau horaire correct.

This PHP Date () Cheatsheat était très utile.

2
its_me