2016-09-22 2 views
1

) timezone 열이있는 사용자로 가득 찬 데이터베이스 (예 : America/New_York)가 있습니다. (그리고 데이터베이스에 오프셋으로 저장하는 것이 더 의미가 있지만이 프로젝트에서는 수행 할 수 없다는 것을 알고 있습니다.) 사용자가 시간대를 변경할 수있는 양식이 있습니다.시간대 이름을 시간대 오프셋으로 변환하는 방법 (역주 :

나는이 다운 드롭 (value =>display) 채우는있다 : 시간대 문자열을 상쇄

protected $timezones = [ 
    '+00:00' => '(UTC +00:00) Western European Time', 
    '+01:00' => '(UTC +01:00) Central European Time', 
    '+02:00' => '(UTC +02:00) Eastern European Time', 
    '+03:00' => '(UTC +03:00) Further-Eastern European Time', 
    '+04:00' => '(UTC +04:00) Gulf Standard Time', 
    '+05:00' => '(UTC +05:00) Pakistan Standard Time', 
    '+05:30' => '(UTC +05:30) Indian Standard Time', 
    '+05:45' => '(UTC +05:45) Nepal Time', 
    '+06:00' => '(UTC +06:00) British Indian Ocean Time', 
    '+07:00' => '(UTC +07:00) Thailand Standard Time', 
    '+08:00' => '(UTC +08:00) Australian Western Standard Time', 
    '+09:00' => '(UTC +09:00) Japan Standard Time', 
    '+10:00' => '(UTC +10:00) Australian Eastern Standard Time', 
    '+10:30' => '(UTC +10:30) Australian Central Daylight Savings Time', 
    '+11:00' => '(UTC +11:00) Australian Eastern Daylight Savings Time', 
    '+12:00' => '(UTC +12:00) New Zealand Standard Time', 
    '+13:00' => '(UTC +13:00) New Zealand Daylight Time', 
    '-01:00' => '(UTC -01:00) Eastern Greenland Time', 
    '-02:00' => '(UTC -02:00) Brasilia Summer Time', 
    '-03:00' => '(UTC -03:00) Atlantic Daylight Time', 
    '-04:00' => '(UTC -04:00) Atlantic Standard Time', 
    '-05:00' => '(UTC -05:00) Central Daylight Time', 
    '-06:00' => '(UTC -06:00) Central Standard Time', 
    '-07:00' => '(UTC -07:00) Pacific Daylight Time', 
    '-08:00' => '(UTC -08:00) Pacific Standard Time', 
    '-09:00' => '(UTC -09:00) Alaska Standard Time', 
    '-10:00' => '(UTC -10:00) Hawaii-Aleutian Standard Time', 
    '-11:00' => '(UTC -11:00) Niue Time', 
]; 

변환하는이 기능 :

/** 
* convert timezone string to offset 
* e.g. "America/New_York" to "-04:00" 
* 
* @param string $timezone time zone represented as a string 
* 
* @return mixed string or null 
*/ 
protected function convertStringToOffset($timezone) 
{ 
    $time = new \DateTime('now', new DateTimeZone($timezone)); 
    if ($time) { 
     return $time->format('P'); 
    } 
} 

그리고이 기능을 여기 내 첫 번째 방법이었다 오프셋을 문자열로 변환하려면 :

/** 
* convert timezone offset to string 
* e.g. "-04:00" to "America/New_York" 
* 
* @param string $offset time zone represented as a numerical offset 
* 
* @return string time zone represented as a string 
*/ 
protected function convertOffsetToString($offset) 
{ 
    // Calculate seconds from offset 
    list($hours, $minutes) = explode(':', $offset); 
    $seconds = $hours * 60 * 60 + $minutes * 60; 
    // Get timezone name from seconds 
    $tz = timezone_name_from_abbr('', $seconds, 1); 
    // Workaround for bug #44780 
    if ($tz === false) { 
     $tz = timezone_name_from_abbr('', $seconds, 0); 
    } 
    return $tz; 
} 
  1. 페이지로드시 데이터베이스에서 시간대를 가져 와서 오프셋으로 변환합니다. 예를 들어 America/New_York-04:00으로 변환되고 (UTC -04:00) Atlantic Standard Time이 선택됩니다.

  2. 이제 사용자는 다른 시간대를 선택하고 양식을 제출합니다. 그런 다음 오프셋을 문자열로 변환 한 다음이를 데이터베이스에 저장합니다.

나는 문제로 실행 :

  • $this->convertOffsetToString('+03:00'); 반환 Europe/Helsinki
  • $this->convertOffsetToString('+04:00'); 반환 Europe/Moscow

하지만! 사용자가 폼에 와서 데이터베이스에 시간대 Europe/Moscow이 있다면 그것은 +03:00과를 얻기의 오프셋에

  • $this->convertStringToOffset('Europe/Moscow'); 반환 +03:00
  • $this->convertStringToOffset('Europe/Helsinki'); 반환

+03:00 그래서, 우리는 문자열을 변환 할 '(UTC +03:00) Further-Eastern European Time'이 선택됩니다.

문제점 (예컨대 +03:00+04:00) 개의 상이한 오프셋은 두 개의 서로 다른 스트링 시간 영역으로 변환한다. 그 두 개의 서로 다른 문자열 시간대는 동일한 오프셋으로 변환됩니다! (예 : +03:00). 누구든지이 문제를 해결할 수있는 안전한 확장 가능한 해결책을 제시 할 수 있습니까?

내게 맨 처음 질문입니다. 내가 충분히 자신을 설명하고 내가 게시 규칙을 위반하지 않았기를 바랍니다.여러분 모두의

+1

TL; DR 오프셋에서 이름으로 변환 할 수 없습니다. 많은 시간대가 오프셋을 공유합니다. –

답변

4

첫째, 데이터베이스의 오프셋으로 그들을 저장하는

아니,하지 않는 방법이 더 이해하게 알고

감사드립니다. 오프셋 변경. 대부분의 시간대는 일광 절약 시간을 일년 중 일부에 적용하고 시간대가 변경되는 날짜/시간이 다릅니다.

사용자는 시간대를 this list의 문자열로 저장 한 다음이를 사용하여 \DateTimeZone의 인스턴스를 만들어야합니다. 예를 들어 : -

$tzString = 'Europe/London'; 
$tz = new \DateTimeZone($tzString); 

그런 다음 같은 것을 사용하여 원하는 시간 오프셋 올바른을 얻을 수 있습니다 : -

$tz->getOffset(new \DateTime()); 

Example. 이 예제에서 생성 된 오프셋은 사용자가보고있는 날짜와 시간에 따라 0에서 3600까지 다양합니다.

사용자 시간대를 저장할 때 오프셋을 올바른 표준 시간대로 변환하지 않아도됩니다.

나는이 문제를 "안전하고 확장 가능한 해결책"이라고 제안합니다.

+1

오프셋 변경 만이 아닙니다. 유럽 ​​연합 (EU)에서 세계의 다른 부분은 알지 못하지만 실제로는 시간대를 전환 (예 : 겨울에는 CET, 여름에는 CEST)합니다. 이것이 PHP가 제공하는'Europe/London' 문법이 그렇게 실용적인 이유입니다. 사용자 프로필 제어판에서 '+ 0100'을 선택하는 것을 싫어합니다. –

+0

@ ÁlvaroGonzález 좋은 지적입니다. 영국에서는 여름에 BST가 있고 겨울에는 GMT가 있습니다. – vascowhite