Bir tarih doğru saat diliminde nasıl gösterilir?


19

Bir içerik türünde bir Datetime Range alanı (field_date) var. İçerik türümü oluşturduktan sonra Başlangıç ​​Tarihini şu şekilde ayarladım:

2017-02-27 19:30:01

resim açıklamasını buraya girin

Şimdi değeri almak ve tarihi başka bir biçimde göstermek istiyorum, bu yüzden aşağıdaki kodu kullanmayı deneyin:

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

Bu benim çıktım:

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

Peki, doğru saat diliminde bir tarih nasıl gösterilir?

Yanıtlar:


22

Sorunun bazı nüanslarla ilgili olduğundan şüpheleniyorum strtotime().

strtotime()hemen hemen her dizeyi alıp bir Unix zaman damgasına dönüştürebilirsiniz. Sorun, dize açık bir saat dilimi içermiyorsa, tarafından ayarlananı kullanmasıdır date_default_timezone_get(). Bu geçerli kullanıcıdan ayarlanmalıdır (hesap proxy'si tarafından ayarlanır). Ancak, çektiğiniz dize $node->field_date->valuedolaylı olarak UTC'de. Başka bir deyişle, dize tarafından ayrıştırılıyor bence strtotime()'UTC / değil' Amerika / New_York 'olarak yorumlanmaktadır.

İyi haber şu ki durumunuzu çok basitleştirebilirsiniz. Tarih aralığı için alan öğesi dört bölümden oluşur

  • 'değer', UTC'de dize olarak başlangıç ​​tarihidir
  • 'start_date', 'değeri' temsil eden bir DrupalDateTime nesnesidir
  • 'end_value', UTC'de dize olarak bitiş tarihidir
  • 'end_date', 'end_value'yu temsil eden bir DrupalDateTime nesnesidir

Düz tarih saat alanı için

  • 'değer' UTC'de dize olarak tarih
  • 'tarih', 'değeri' temsil eden bir DrupalDateTime nesnesidir

Böylece, DrupalDateTime()nesneyle doğrudan çalışabilirsiniz . Buna ek olarak, söz konusu date.formatterhizmet, sayfayı varsayılan olarak görüntüleyen kullanıcının kullandığı uygun saat dilimini de çekmelidir (kullanıcının etkin dilini kullanmaya ek olarak).

Bunun gibi bir şeyin işe yarayacağından şüpheleniyorum

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

Not Sistemin hangi saat diliminin kullanımda olduğunu düşündüğünü görebilmeniz için 'P' biçiminde yer tutucusu ekledim.

Yönetici / config / bölge / ayarlarında doğru saat dilimini ayarladığınızdan ve kullanıcı saat diliminizin beklediğiniz ayar olduğundan emin olun. Ayrıca php.ini dosyasında doğru saat dilimi ayarının yapılmış olduğundan emin olun ( date.timezoneayar budur); Bu ayarlanmadığında garip şeyler olur (Ve başımın üstünden, kurulumcuda veya durum raporunda ayarlanmadığında bir uyarıya neden olup olmadığını hatırlamıyorum. sorunu hatırlıyorum, ancak taahhüt).


1
@mpdonadio Yardım için teşekkürler! dateDrupalDateTime erişim özelliği hakkında bilmiyordum . Meraktan nasıl anladınız? Alanımın bu türden olduğunu anlayabildim, DateTimeItemancak içeride bu sınıf için bir date(veya value) kamu üyesi olduğu açık görünmüyor .
Pzanno

1
@Pzanno Ben Drupal 8 çekirdekli datetime.module eş sürdürücüsüyüm ve aynı zamanda birçok temel tarih / saatle ilgili şeyler benim yoluma geliyor :) Özellikler sihirli yöntemlerdir. Eğer bakarsanız, DateTimeItem::propertyDefinitions()neyin maruz kaldığını göreceksiniz. Sonra DateTimeComputed::getValue()bunun nasıl çalıştığını görmek için bakın. Tüm Item sınıfları bu şekilde incelenebilir, ancak sadece bir avuç hesaplanmış değer kullanır. Keşke bunu API'ye göstermenin daha iyi bir yolu olsaydı.
mpdonadio

@mpdonadio açıklama için teşekkürler! Hatta tanımlanmış oldukları gerçeğini kaçırdım DateTimeItem::propertyDefinitions(). Bazı sihirli yöntemler olduğunu düşündüm, ancak bunların nasıl oluşturulduğunu anlamak istedim, böylece diğer alanlara nasıl erişebileceğimi daha iyi anlayabiliyordum. Dediğiniz gibi, API'nin açıkta kalması iyi olurdu, ancak bu yardımcı olur. Tekrar teşekkürler.
Pzanno

1
Benim durumumda, ben yapmak zorunda $node->field_date->dateyerine, $node->field_date->start_date.
Marcos Buarque

2
Bu yanıtı Sahne, çünkü bu şimdiye kadar bulduğum en bilgilendirici Drupal belgeleri.
Ryan H

6

PHP DateTime ile saat dilimi dönüştürme ele dayanarak Kodumu bu için değiştirdim:

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

Ve şimdi çıktı tarihim iyi:

2017-02-27 19:30:01

Bu çalışıyor. Ama eminim Drupal API kullanarak bunu yapmanın bir yolu vardır.


1
Önceki yorumumu kaldırdım. DrupalDateTime, Drupal kullanıcısının saat dilimini ayarlamaz.
17'de oknate

Benim durumumda bunu herhangi bir tarih fonksiyon çağrısından önce kullandım:date_default_timezone_set(drupal_get_user_timezone());
Roger

Bunun için teşekkürler. Gerçekten drupal.stackexchange.com/q/256490/2089 ile bana yardımcı oldu .
colan

@colan size bir zevk veriyor, eğer cevabımın yararlı olduğunu düşünüyorsanız, diğer cevabı da kontrol edebileceğinizi düşünüyorum.
Adrian Cid Almaguer

4

Genellikle bu şekilde çözerim .:

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

2

Bu benim için çalıştı:

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

Benim için de işe yarıyor `$ dDate = DrupalDateTime :: createFromTimestamp ($ form_state-> getValue ('service_date') -> getTimestamp (), 'UTC'); // Böyle kullanın. $ dDate-> format ('Ymd \ TH: i: s'); ``
Yogesh Kushwaha

1

Bu kod benim için çalışıyor.

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

0

Bu cevapların hiçbiri benim için işe yaramadı. Ben nihayet sonuçlandı:

$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

Bu snippet'i tarihlerle çalışmak için kullanıyorum:

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

Datetime nesnesi hakkında daha fazla bilgiyi buradan edinebilirsiniz.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.