web-dev-qa-db-ja.com

正しいタイムゾーンで日付を表示するにはどうすればよいですか?

コンテンツタイプに日時範囲フィールド(field_date)があります。コンテンツタイプを作成したら、開始日を次のように設定します。

2017-02-27 19:30:01

enter image description here

次に、値を取得して日付を別の形式で表示したいので、次のコードを使用してみます。

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

これは私の出力です:

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

では、正しいタイムゾーンで日付を表示するにはどうすればよいですか?

20

問題は strtotime() のニュアンスの一部に関係しているのではないかと思います。

strtotime()は、ほぼすべての文字列を取り、それをUnixタイムスタンプに変換できます。問題は、文字列に明示的なタイムゾーンが含まれていない場合、文字列は date_default_timezone_get() によって設定されたものを使用することです。ただし、現在のユーザーから設定する必要があります(アカウントプロキシによって設定されます)。ただし、_$node->field_date->value_から引き出している文字列は、暗黙的にUTCにあります。つまり、文字列はstrtotime()によって解析されていると思います。これは、 'UTC'ではなく 'America/New_York'として解釈されているためです。

良いニュースは、状況を大幅に簡素化できることです。日付範囲のフィールドアイテムは4つの部分で構成されます

  • 「値」はUTCの文字列としての開始日です
  • 「start_date」は「value」を表すDrupalDateTimeオブジェクトです
  • 「end_value」はUTCの文字列としての終了日です
  • 「end_date」は「end_value」を表すDrupalDateTimeオブジェクトです

プレーンな日付時刻フィールドの場合、

  • 「値」はUTCの文字列としての日付です
  • 「日付」は「値」を表すDrupalDateTimeオブジェクトです

したがって、 DrupalDateTime() オブジェクトを直接操作できます。さらに、その_date.formatter_サービスは、(ユーザーのアクティブな言語の使用に加えて)デフォルトでページを表示しているユーザーが使用している適切なタイムゾーンを取得する必要があります。

このようなものがうまくいくと思います

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

ここに「P」形式のプレースホルダーを追加したので、システムがどのタイムゾーンを使用していると考えているかを確認できます。

Admin/config/regional/settingsで適切なタイムゾーンが設定されていること、およびユーザーのタイムゾーンが想定どおりであることを確認してください。また、php.iniに適切なタイムゾーンが設定されていることを確認してください(これは_date.timezone_設定です)。これが設定されていないときに奇妙なことが起こります(そして、頭から離れて、それが設定されていないときにインストーラーまたはステータスレポートに警告を引き起こしたかどうか覚えていません。問題を覚えていますが、それが関与する)。

24
mpdonadio

に基づいてPHP DateTime でタイムゾーン変換を処理します。コードを次のように変更しました:

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

そして今私の出力日はそれでいいです:

2017-02-27 19:30:01

これは機能します。しかし、Drupal APIを使用してこれを行う方法があると確信しています。

6

私は通常、この方法で解決します。:

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

これは私のために働きました:

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

このコードは私のために働いています。

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

私はこのスニペットを使用して日付を操作します:

<?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オブジェクトについてのより多くの情報を得ることができます

0
Ben Cassinat

これらの他の答えはどれも私にとってうまくいきませんでした。これは最終的に私が終わったものです:

$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