올바른 시간대로 날짜를 표시하는 방법은 무엇입니까?


18

콘텐츠 유형에 날짜 시간 범위 필드 (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

그렇다면 올바른 시간대로 날짜를 표시하는 방법은 무엇입니까?

답변:


21

문제가의 미묘한 차이와 관련이 있다고 생각합니다 strtotime().

strtotime()거의 모든 문자열을 가져 와서 Unix 타임 스탬프로 변환 할 수 있습니다. 문제는 문자열에 명시적인 시간대가 포함되어 있지 않으면에서 설정 한 것을 사용한다는 것 date_default_timezone_get()입니다. 하지만 현재 사용자로부터 설정해야합니다 (계정 프록시에서 설정). 그러나 꺼내는 문자열 $node->field_date->value은 암시 적으로 UTC입니다. 즉, 문자열이 파싱되는 strtotime()것은 'UTC'가 아닌 'America / New_York'와 같이 해석 되고 있다고 생각합니다 .

좋은 소식은 상황을 많이 단순화 할 수 있다는 것입니다. 날짜 범위의 필드 항목은 네 부분으로 구성됩니다

  • 'value'는 UTC의 문자열로 시작 날짜입니다
  • 'start_date'는 'value'를 나타내는 DrupalDateTime 객체입니다.
  • 'end_value'는 UTC의 문자열로 끝나는 날짜입니다.
  • 'end_date'는 'end_value'를 나타내는 DrupalDateTime 객체입니다.

일반 날짜 시간 필드의 경우

  • 'value'는 UTC의 문자열 날짜입니다.
  • 'date'는 'value'를 나타내는 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 도와 주셔서 감사합니다! 내가 몰랐던 dateDrupalDateTime에 액세스 할 수있는 기능입니다. 호기심에서 어떻게 알아 냈습니까? 나는 내 필드가 유형 DateTimeItem이라는 것을 알 수 있었지만 거기에는 그 클래스에 대한 date(또는 value) 공개 멤버가 있는지 분명하지 않습니다 .
Pzanno

1
@Pzanno 저는 Drupal 8 핵심 datetime.module 공동 유지 관리자이며 다른 핵심 날짜 / 시간 관련 항목도 많이 있습니다. :) 속성은 마법의 방법입니다. 를 보면 DateTimeItem::propertyDefinitions()노출 된 것을 볼 수 있습니다. 그런 다음 DateTimeComputed::getValue()어떻게 작동하는지 살펴보십시오 . 모든 항목 클래스는 그런 식으로 검사 할 수 있지만 소수의 계산 된 값만 사용됩니다. API에 이것을 노출시키는 더 좋은 방법이 있었으면 좋겠습니다.
mpdonadio

@mpdonadio 설명해 주셔서 감사합니다! 나는 그들이 심지어에 정의되어 있다는 사실을 놓쳤다 DateTimeItem::propertyDefinitions(). 나는 어떤 마법적인 방법들이 일어나고 있다고 생각했지만, 그것들이 어떻게 만들어 졌는지 이해하고 싶었 기 때문에 다른 필드에 액세스하는 방법을 더 잘 이해할 수있었습니다. 당신이 말했듯이 API가 노출되면 좋을 것이지만 도움이됩니다. 다시 감사합니다.
Pzanno

1
제 경우에는 $node->field_date->date대신에해야했습니다 $node->field_date->start_date.
Marcos Buarque

2
이것이 내가 찾은 Drupal 문서 중 가장 유익한 정보이므로이 응답에 대한 제안입니다.
Ryan 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


@colan 당신이 내 대답이 유용하다고 생각하면 다른 답변도 확인할 수 있다고 생각하면 즐거움이 도움이됩니다.
Adrian Cid Almaguer

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 객체 에 대한 자세한 내용은 여기를 참조하십시오.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.