Cum să afișați o dată în fusul orar corect? (Drupal, 8, Datetime)

Adrian Cid Almaguer a intrebat.
a intrebat.

Am un câmp Datetime Range (field_date) într-un tip de conținut. Odată ce am creat tipul de conținut, am setat Data de început ca:

2017-02-27 19:30:01

Acum vreau să obțin valoarea și să arăt data în alt format, așa că încerc să folosesc următorul cod:

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

Acesta este rezultatul meu:

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

Deci, cum să afișați o dată în fusul orar corect?

7 răspunsuri
mpdonadio

Bănuiesc că problema are legătură cu unele dintre nuanțele din strtotime().

strtotime() poate lua aproape orice șir de caractere și îl poate converti într-un timestamp Unix. Problema este că, atunci când șirul nu conține un fus orar explicit, va folosi ceea ce este setat de către date_default_timezone_get(). Totuși, acesta ar trebui să fie setat de utilizatorul curent (este setat de către proxy-ul contului). Cu toate acestea, șirul pe care îl scoateți din $node->field_date->value este implicit în UTC. Cu alte cuvinte, cred că șirul este analizat de către strtotime() este interpretat ca fiind în „America/New_York” și nu „UTC”.

Vestea bună este că vă puteți simplifica mult situația. Elementul de câmp pentru un interval de date este format din patru părți

  • „value” este data de început ca șir de caractere în UTC
  • ‘start_date’ este un obiect DrupalDateTime care reprezintă ‘value’
  • „end_value” este data de sfârșit ca șir de caractere în UTC
  • „end_date” este un obiect DrupalDateTime care reprezintă „end_value”.

Pentru un câmp simplu de dată și oră, acestea sunt

  • „value” este data sub forma unui șir de caractere în UTC
  • „date” este un obiect DrupalDateTime care reprezintă „value”.

Prin urmare, puteți lucra cu DrupalDateTime() în mod direct. În plus, acest lucru date.formatter serviciu ar trebui să extragă în mod implicit fusul orar corespunzător utilizat de utilizatorul care vizualizează pagina (pe lângă utilizarea limbii active a utilizatorului).

Bănuiesc că ceva de genul acesta va funcționa

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

Rețineți că am adăugat acolo un marcaj de format „P” pentru a vedea ce fus orar crede sistemul că este utilizat.

Asigurați-vă că aveți configurat fusul orar corespunzător în admin/config/regional/settings și că fusul orar al utilizatorului este cel pe care îl așteptați. De asemenea, asigurați-vă că aveți setat fusul orar corect în php.ini (este vorba de secțiunea date.timezone setting); se întâmplă lucruri ciudate atunci când nu este setat (și, din capul locului, nu-mi amintesc dacă acest lucru provoacă un avertisment în programul de instalare sau pe raportul de stare atunci când nu este setat. Îmi amintesc problema, dar nu și dacă a fost comisă).

Comentarii

  • @mpdonadio Mulțumesc pentru ajutor! Nu știam despre date caracteristică de accesare a DrupalDateTime. Din curiozitate, cum ați descoperit acest lucru? Am reușit să-mi dau seama că câmpul meu era de tipul DateTimeItem dar în interiorul acestuia nu pare evident că există un câmp date (sau value) membru public pentru acea clasă. –  > Por Pzanno.
  • @Pzanno Sunt co-maintainerul nucleului Drupal 8 datetime.module, și, de asemenea, o mulțime de alte lucruri legate de date/timp îmi vin în cale 🙂 Proprietățile sunt metode magice. Dacă vă uitați la DateTimeItem::propertyDefinitions(), , veți vedea ce este expus. Apoi, uitați-vă la DateTimeComputed::getValue() pentru a vedea cum funcționează. Toate clasele Item pot fi examinate în acest mod, dar numai câteva dintre ele utilizează valori calculate. Mi-aș dori să existe o modalitate mai bună de a expune acest lucru în API. –  > Por mpdonadio.
  • @mpdonadio mulțumesc pentru explicație! Mi-a scăpat faptul că au fost definite chiar în DateTimeItem::propertyDefinitions(). Mi-am dat seama că se întâmplă niște metode magice, dar am vrut să înțeleg cum au fost create acestea pentru a putea înțelege mai bine cum să accesez și alte câmpuri. După cum ați spus, ar fi frumos dacă API-ul ar fi expus, dar acest lucru ajută. Mulțumesc din nou. –  > Por Pzanno.
  • În cazul meu, a trebuit să fac următoarele $node->field_date->date, , în loc de $node->field_date->start_date. –  > Por Marcos Buarque.
  • Props la acest răspuns, deoarece este cea mai informativă parte a documentației Drupal pe care am găsit-o vreodată. –  > Por Ryan H.
Adrian Cid Almaguer

Cu sediul în Gestionarea conversiei fusului orar cu PHP DateTime Mi-am modificat codul la acest lucru:

$node = Node::load(2100);
$userTimezone = new DateTimeZone(date_default_timezone_get());
$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);

Și acum data mea de ieșire este în regulă:

2017-02-27 19:30:01

Acest lucru funcționează. Dar sunt sigur că există o modalitate de a face acest lucru folosind API-ul Drupal.

Comentarii

  • Am eliminat comentariul meu anterior. DrupalDateTime nu se ajustează în funcție de fusul orar al utilizatorului Drupal. –  > Por oknate.
  • În cazul meu, am folosit doar acest lucru înainte de orice apel al funcției date: date_default_timezone_set(drupal_get_user_timezone()); –  > Por Roger.
  • Vă mulțumim pentru asta. M-a ajutat foarte mult cu drupal.stackexchange.com/q/256490/2089. –  > Por colan.
  • @colan o plăcere să vă ajut, dacă credeți că răspunsul meu este util cred că puteți verifica și celălalt răspuns. –  > Por Adrian Cid Almaguer.
Ytacol

De obicei, eu rezolv în felul următor.:

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

Dan Poenaru

Acest lucru a funcționat pentru mine:

// 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-dTH:i:s");

Comentarii

  • Funcționează și pentru mine ` $dDate = DrupalDateTime::createFromTimestamp($form_state->getValue(‘service_date’)->getTimestamp(), ‘UTC’); // Folosiți așa. $dDate->format(‘Y-m-d-dTH:i:s’);` –  > Por Yogesh Kushwaha.
Arun Mishra

Acest cod funcționează pentru mine.

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

user1359

Nici unul dintre aceste alte răspunsuri nu a funcționat pentru mine. Asta este ceea ce am ajuns în cele din urmă cu:

$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-dTH:i:s', 'EST');

benftwc

Folosesc acest fragment pentru a lucra cu datele :

<?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());
    }
}

Puteți obține mai multe informații despre obiectul Datetime aici

Tags:,