如何在正确的时区显示日期?


19

我在内容类型中有一个日期时间范围字段(field_date)。创建内容类型后,将开始日期设置为:

2017-02-27 19:30:01

在此处输入图片说明

现在,我想获取值并以其他格式显示日期,因此请尝试使用以下代码:

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

那么,如何显示正确时区的日期?

Answers:


22

我怀疑问题与的某些细微差别有关strtotime()

strtotime()可以接受几乎任何字符串,并将其转换为Unix时间戳。问题是,当字符串不包含显式时区时,它将使用设置的值date_default_timezone_get()。不过,该设置应由当前用户设置(由帐户代理设置)。但是,要拉出的字符串$node->field_date->value在UTC 中是隐式的。换句话说,我认为该字符串被解析strtotime()为“ America / New_York”而不是“ UTC”。

好消息是您可以大大简化您的情况。日期范围的字段项目由四部分组成

  • 'value'是UTC中字符串形式的开始日期
  • 'start_date'是一个DrupalDateTime对象,表示'value'
  • '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设置);如果未设置此设置,则会发生奇怪的事情(而且,我不由自主地回想起这是否会在安装程序或状态报告中引起警告)。承诺)。


1
@mpdonadio感谢您的帮助!我不知道date访问DrupalDateTime 的功能。出于好奇,您如何解决这个问题?我能够弄清楚我的字段是该类型的,DateTimeItem但是在其中似乎并没有发现该类有date(或value)公共成员。
Pzanno

1
@Pzanno我是Drupal 8核心datetime.module的共同维护者,还有许多其他与日期/时间相关的核心东西也来了:)这些属性是魔术方法。如果您看一下DateTimeItem::propertyDefinitions(),您将看到暴露的东西。然后看一下它DateTimeComputed::getValue()是如何工作的。可以通过这种方式检查所有Item类,但是只有极少数使用计算值。我希望有一个更好的方法可以将此公开给API。
mpdonadio

@mpdonadio感谢您的解释!我错过了它们甚至在中定义的事实DateTimeItem::propertyDefinitions()。我认为发生了一些魔术方法,但是想了解它们是如何创建的,因此我也可以更好地了解如何访问其他领域。就像您说的那样,如果公开了该API会很好,但这会有所帮助。再次感谢。
Pzanno

1
就我而言,我必须做$node->field_date->date,而不是$node->field_date->start_date
Marcos Buarque

2
支持此响应,因为这是我所找到的最丰富的Drupal文档。
瑞安H

6

基于使用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的方法。


1
我删除了之前的评论。DrupalDateTime不适用于Drupal用户的时区。
oknate

就我而言,我只是在任何日期函数调用之前使用了它:date_default_timezone_set(drupal_get_user_timezone());
Roger

谢谢你 它确实对drupal.stackexchange.com/q/256490/2089有帮助。
科兰

@colan很乐意为您提供帮助,如果您认为我的答案有用,我想您也可以查看其他答案。
阿德里安·西德·阿尔玛格

4

我通常以这种方式解决它:

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

这为我工作:

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

它也对我有用`$ dDate = DrupalDateTime :: createFromTimestamp($ form_state-> getValue('service_date')-> getTimestamp(),'UTC'); //这样使用。$ dDate-> format('Ymd \ TH:i:s');`
Yogesh Kushwaha

1

该代码对我有用。

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

这些其他答案对我都不起作用。这是我最终得到的结果:

$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

我使用此代码段处理日期:

<?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对象的更多信息。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.