web-dev-qa-db-fra.com

Comment afficher une date dans le fuseau horaire correct?

J'ai un champ de plage de dates (field_date) dans un type de contenu. Une fois que j'ai créé mon type de contenu, j'ai défini la date de début comme suit:

2017-02-27 19:30:01

enter image description here

Maintenant, je veux obtenir la valeur et afficher la date dans un autre format, essayez donc d'utiliser le code suivant:

// Loading the node.
$node = Node::load(2100);
// Getting the start date value.
$date = $node->field_date->value;
// Printing to see what is the output.
dpm($node->field_date->value);
$date = strtotime($date);
// Printing my timezone.
dpm(drupal_get_user_timezone());
// Applying my custom format.
$date = \Drupal::service('date.formatter')->format($date, 'custom', 'Y-m-d H:i:s', drupal_get_user_timezone());
// Printing to see the output.
dpm($date);

Voici ma sortie:

// It's fine.
2017-02-28T00:30:01
// Its fine.
America/New_York
// This is not what I waiting for. I'm waiting here: 2017-02-27 19:30:01
2017-02-28 00:30:01

Alors, comment afficher une date dans le fuseau horaire correct?

20
Adrian Cid Almaguer

Je soupçonne que le problème a à voir avec certaines des nuances de strtotime() .

strtotime() peut prendre n'importe quelle chaîne et la convertir en horodatage Unix. Le problème est que lorsque la chaîne ne contient pas de fuseau horaire explicite, elle utilise ce qui est défini par date_default_timezone_get() . Cependant, cela doit être défini par l'utilisateur actuel (il est défini par le proxy de compte). Cependant, la chaîne que vous extrayez de $node->field_date->value Est implicitement en UTC. En d'autres termes, je pense que la chaîne est analysée par strtotime() est interprétée comme dans 'America/New_York' et non dans 'UTC'.

La bonne nouvelle est que vous pouvez beaucoup simplifier votre situation. L'élément de champ pour une plage de dates se compose de quatre parties

  • 'valeur' ​​est la date de début sous forme de chaîne en UTC
  • 'start_date' est un objet DrupalDateTime représentant 'value'
  • 'end_value' est la date de fin sous forme de chaîne en UTC
  • 'end_date' est un objet DrupalDateTime représentant 'end_value'

Pour un champ date-heure simple, ils sont

  • 'valeur' ​​est la date sous forme de chaîne en UTC
  • 'date' est un objet DrupalDateTime représentant 'valeur'

Vous pouvez donc travailler directement avec l'objet DrupalDateTime() . En outre, ce service date.formatter Doit extraire le fuseau horaire approprié utilisé par l'utilisateur qui affiche la page par défaut (en plus d'utiliser la langue active de l'utilisateur).

Je soupçonne que quelque chose comme ça fonctionnera

$node = Node::load(2100);
$start_date = $node->field_date->start_date;
$formatted = \Drupal::service('date.formatter')->format(
  $start_date->getTimestamp(), 'custom', 'Y-m-d H:i:s P'
);

Remarque J'ai ajouté un espace réservé au format "P" pour que vous puissiez voir quel fuseau horaire le système pense être utilisé.

Assurez-vous que le fuseau horaire approprié est configuré dans admin/config/regional/settings et que le fuseau horaire de votre utilisateur correspond à ce que vous attendez. Assurez-vous également que le fuseau horaire approprié est défini dans votre php.ini (c'est le paramètre date.timezone); des choses étranges se produisent lorsque ce n'est pas défini (Et du haut de ma tête, je ne me souviens pas si cela provoque un avertissement dans l'installateur ou dans le rapport d'état lorsqu'il n'est pas défini. Je me souviens du problème, mais pas s'il s'est engagé).

24
mpdonadio

Basé sur Gestion de la conversion du fuseau horaire avec PHP DateTime J'ai modifié mon code en ceci:

$node = Node::load(2100);
$userTimezone = new DateTimeZone(drupal_get_user_timezone());
$gmtTimezone = new DateTimeZone('GMT');
$myDateTime = new DateTime($node->field_date->value, $gmtTimezone);
$offset = $userTimezone->getOffset($myDateTime);
$myInterval = DateInterval::createFromDateString((string)$offset . 'seconds');
$myDateTime->add($myInterval);
$result = $myDateTime->format('Y-m-d H:i:s');
dpm($result);

Et maintenant ma date de sortie c'est bien:

2017-02-27 19:30:01

Cela marche. Mais je suis sûr qu'il existe un moyen de le faire en utilisant l'API Drupal.

6
Adrian Cid Almaguer

Je le résout généralement de cette façon:

node = Node::load(1);    
$date_original= new DrupalDateTime( $node->field_date->value , 'UTC' );     
$result = \Drupal::service('date.formatter')->format( $date_original->getTimestamp(), 'custom', 'Y-m-d H:i:s'  );    
dpm( $result );
4
Ytacol

Cela a fonctionné pour moi:

// Take the timestamp.
$timestamp = $form_state->getValue($form_field)->getTimestamp();
// Convert to UTC - the way its saved in database.
$date = DrupalDateTime::createFromTimestamp($timestamp, 'UTC');
// Add on the current entity.
$this->entity->{$db_field}->value = $date->format("Y-m-d\TH:i:s");
2
Dan Poenaru

Ce code fonctionne pour moi.

// set use timezone
userTimezone = new DateTimeZone(drupal_get_user_timezone());
// set gmt timezone
$gmtTimezone = new DateTimeZone('GMT');
// Take the timestamp.
$start_date = $val['field_start_time_value'];    
$startDateTime = new DateTime($start_date, $gmtTimezone);
$offset = $userTimezone->getOffset($startDateTime);
$startInterval = DateInterval::createFromDateString((string)$offset . 'seconds');
$startDateTime->add($startInterval);
$result = $startDateTime->format('Y-m-d H:i:s');
1
Arun Mishra

J'utilise cet extrait pour travailler avec des dates:

<?php
class MyApp extends ControllerBase
{
    public function output() 
    {
        $dtime = DateTime::createFromFormat("d/m/Y - H:I:s", "22/12/1999 - 22:55:12", $this->getDateTimeZone());
        $time = $dtime->format('r');
        // My code goes here
    }

    private function getDateTimeZone()
    {
        return new DateTimeZone(drupal_get_user_timezone());
    }
}

Vous pouvez obtenir plus d'informations sur l'objet Datetime ici

0
Ben Cassinat

Aucune de ces autres réponses n'a fonctionné pour moi. C'est ce que je me suis finalement retrouvé avec:

$range_start = DrupalDatetime::createFromTimestamp((int)$start_date); // unix timestamp
$range_start->setTimezone(new \Datetimezone('EST'));
$node->field_date_range->value = format_date(
  $range_start->getTimestamp() , 'custom', 'Y-m-d\TH:i:s', 'EST');
0
user1359