Làm thế nào để hiển thị một ngày trong múi giờ chính xác?


18

Tôi có trường Phạm vi thời gian (field_date) trong một loại nội dung. Khi tôi tạo loại nội dung của mình, tôi đặt Ngày bắt đầu là:

2017 / 02-27 19:30:01

nhập mô tả hình ảnh ở đây

Bây giờ tôi muốn lấy giá trị và hiển thị ngày ở định dạng khác, vì vậy hãy thử sử dụng mã sau:

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

Đây là đầu ra của tôi:

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

Vì vậy, làm thế nào để hiển thị một ngày trong múi giờ chính xác?

Câu trả lời:


20

Tôi nghi ngờ vấn đề phải làm với một số sắc thái của strtotime().

strtotime()có thể lấy bất kỳ chuỗi nào và chuyển đổi nó thành dấu thời gian Unix. Vấn đề là khi chuỗi không chứa múi giờ rõ ràng, nó sẽ sử dụng những gì được đặt bởi date_default_timezone_get(). Tuy nhiên, điều đó nên được đặt từ người dùng hiện tại (nó được đặt bởi proxy tài khoản). Tuy nhiên, chuỗi mà bạn đang rút ra $node->field_date->valuehoàn toàn nằm trong UTC. Nói cách khác, tôi nghĩ rằng chuỗi đang được phân tích cú pháp bằng cách strtotime()được hiểu như trong 'America / New_York' chứ không phải 'UTC'.

Tin tốt là bạn có thể đơn giản hóa tình huống của mình rất nhiều. Mục trường cho phạm vi ngày bao gồm bốn phần

  • 'value' là ngày bắt đầu dưới dạng chuỗi trong UTC
  • 'start_date' là một đối tượng DrupalDateTime đại diện cho 'giá trị'
  • 'end_value' là ngày kết thúc dưới dạng chuỗi trong UTC
  • 'end_date' là một đối tượng DrupalDateTime đại diện cho 'end_value'

Đối với trường thời gian ngày đơn giản, chúng là

  • 'value' là ngày dưới dạng chuỗi trong UTC
  • 'ngày' là một đối tượng DrupalDateTime đại diện cho 'giá trị'

Vì vậy, bạn có thể làm việc với DrupalDateTime()đối tượng trực tiếp. Ngoài ra, date.formatterdịch vụ đó sẽ kéo theo múi giờ thích hợp được sử dụng bởi người dùng đang xem trang theo mặc định (ngoài việc sử dụng ngôn ngữ hoạt động của người dùng).

Tôi nghi ngờ một cái gì đó như thế này sẽ làm việc

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

Lưu ý Tôi đã thêm trình giữ chỗ định dạng 'P' trong đó để bạn có thể thấy múi giờ mà hệ thống nghĩ là đang sử dụng.

Đảm bảo rằng bạn có múi giờ thích hợp được thiết lập trên admin / config / khu vực / cài đặt và múi giờ người dùng của bạn là những gì bạn đang mong đợi. Đồng thời đảm bảo rằng bạn có múi giờ thích hợp được đặt trong php.ini (đó là date.timezonecài đặt); những điều kỳ lạ xảy ra khi điều này không được đặt (Và ngoài đỉnh đầu, tôi không nhớ nếu điều đó gây ra cảnh báo trong trình cài đặt hoặc trên báo cáo trạng thái khi không được đặt. Tôi nhớ vấn đề, nhưng không biết nó có cam kết).


1
@mpdonadio Cảm ơn sự giúp đỡ! Tôi không biết về datetính năng truy cập DrupalDateTime. Vì tò mò làm thế nào bạn tìm ra điều này? Tôi đã có thể nhận ra rằng lĩnh vực của tôi thuộc loại DateTimeItemnhưng trong đó có vẻ không rõ ràng rằng có một date(hoặc value) thành viên công khai cho lớp đó.
Pzanno

1
@Pzanno Tôi là người đồng bảo trì datetime.module lõi 8 của Drupal, và cũng có rất nhiều thứ liên quan đến ngày / thời gian cốt lõi khác theo cách của tôi :) Các thuộc tính là phương pháp kỳ diệu. Nếu bạn nhìn vào DateTimeItem::propertyDefinitions(), bạn sẽ thấy những gì được tiếp xúc. Sau đó nhìn vào DateTimeComputed::getValue()để xem làm thế nào hoạt động. Tất cả các lớp Item có thể được kiểm tra theo cách đó, nhưng chỉ một số ít sử dụng các giá trị được tính toán. Tôi ước có một cách tốt hơn để đưa ra điều này với API.
mpdon Arena

@mpdonadio cảm ơn đã giải thích! Tôi đã bỏ lỡ thực tế rằng họ thậm chí đã được xác định trong DateTimeItem::propertyDefinitions(). Tôi hình dung có một số phương pháp kỳ diệu xảy ra, nhưng muốn hiểu làm thế nào chúng được tạo ra để tôi có thể hiểu rõ hơn về cách truy cập vào các lĩnh vực khác. Giống như bạn đã nói sẽ rất tuyệt nếu API được phơi bày, nhưng điều này có ích. Cảm ơn một lần nữa.
Pzanno

1
Trong trường hợp của tôi, tôi phải làm $node->field_date->date, thay vì $node->field_date->start_date.
Marcos Buarque

2
Đạo cụ cho phản hồi này vì đây là phần thông tin nhất về tài liệu Drupal mà tôi đã tìm thấy.
Ryan H

6

Dựa trên Xử lý chuyển đổi múi giờ với PHP DateTime, tôi đã sửa đổi mã của mình thành:

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

Và bây giờ ngày đầu ra của tôi là tốt:

2017-02-27 19:30:01

Những công việc này. Nhưng tôi chắc chắn rằng có một cách để làm điều này bằng API Drupal.


1
Tôi đã xóa bình luận trước đây của tôi. DrupalDateTime không điều chỉnh múi giờ của Drupal.
oknate

Trong trường hợp của tôi, tôi chỉ sử dụng điều này trước bất kỳ cuộc gọi chức năng ngày nào:date_default_timezone_set(drupal_get_user_timezone());
Roger

Cảm ơn vì điều đó. Nó thực sự giúp tôi với drupal.stackexchange.com/q/256490/2089 .
colan

@colan một niềm vui giúp bạn, nếu bạn nghĩ rằng câu trả lời của tôi là hữu ích tôi nghĩ rằng bạn cũng có thể kiểm tra câu trả lời khác.
Adrian Cid Almaguer

4

Tôi thường giải quyết nó theo cách này.:

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

Điều này làm việc cho tôi:

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

Nó cũng hoạt động với tôi `$ dDate = DrupalDateTime :: createdFromTimestamp ($ form_state-> getValue ('service_date') -> getTimestamp (), 'UTC'); // Sử dụng như thế này. định dạng $ dDate-> ('Ymd \ TH: i: s'); `
Yogesh Kushwaha

1

Mã này đang làm việc cho tôi.

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

Không có câu trả lời nào khác làm việc cho tôi. Đây là những gì tôi cuối cùng đã kết thúc với:

$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

Tôi sử dụng đoạn mã này để làm việc với ngày:

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

Bạn có thể nhận thêm thông tin về đối tượng Datetime tại đây

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.