2013-09-21 3 views
1

Я работаю над проектом PHP, который занимается временем и датами и пользовательскими часами.Проблема с часовыми поясами в PHP

Он должен быть точным, поэтому я сохраняю DateTime и временную метку в DB как время UTC.

В UI/Frontend я пытаюсь отобразить DateTimes на основе TimeZone пользователя.

Я сделал это маленькое демо-класс ниже, чтобы продемонстрировать свою текущую проблему.

Метод createTimeCard() должен создать DateTime в UTC времени и, похоже, работает отлично.

Метод get12HourDateTime($date, $format = 'Y-m-d h:i:s a') используется для отображения DateTime пользователю, имеющему собственный часовой пояс, а также в 12-часовом формате. К сожалению, здесь возникают мои проблемы. Независимо от того, какой часовой пояс установлен здесь, он всегда возвращает время UTC!

Может ли кто-нибудь помочь мне выяснить, что я делаю неправильно?

<?php 

class TimeTest{ 

    public $dateTime; 
    public $dateFormat = 'Y-m-d H:i:s'; 
    public $timeZone; 

    public function __construct() 
    { 
     $this->timeZone = new DateTimeZone('UTC'); 
     $this->dateTime = new DateTime(null, $this->timeZone); 
    } 

    // Create a new time card record when a User Clocks In 
    public function createTimeCard() 
    { 

     $dateTime = $this->dateTime; 
     $dateFormat = $this->dateFormat; 

     // Create both Timecard and timecard record tables in a Transaction 
     $record = array(
      'clock_in_datetime' => $dateTime->format($dateFormat), 
      'clock_in_timestamp' => $dateTime->getTimestamp() 
     ); 

     return $record; 
    } 




    // Get 12 hour time format for a DateTime string 
    // Simulates getting a DateTime with a USER's TimeZone' 
    public function get12HourDateTime($date, $format = 'Y-m-d h:i:s a') 
    { 
     $timeZone = new DateTimeZone('America/Chicago'); 
     $date = new DateTime($date, $timeZone); 

     // Also tried this with no luck 
     $date->setTimezone(new DateTimeZone('America/Chicago')); 

     return $date->format($format) ; 
    } 



} 


$timeCard = new TimeTest; 

$records = $timeCard->createTimeCard(); 

echo '<pre>'; 
print_r($records); 
echo '</pre>'; 

echo $timeCard->get12HourDateTime($records['clock_in_datetime'], 'Y-m-d h:i:s a'); 

?> 

ВЫВОД

Array 
(
    [clock_in_datetime] => 2013-09-21 19:28:01 
    [clock_in_timestamp] => 1379791681 
) 

//This is in 12 hour format but is not in the new time zone! 
2013-09-21 07:28:01 pm 
+0

Надеюсь, вы понимаете, что createTimeCard фактически не создает часы. Дата-время было установлено, когда вы $ timeCard = new TimeTest; – gview

ответ

2

DateTime говорит:

Примечание Параметр $ часового пояса и текущей временной зоны игнорируются, когда параметр времени $ либо является отметка о времени UNIX (например, @ 946684800) или указывает часовой пояс (например, 2010-01-28T15: 00: 00 + 02: 00).

В этом случае?

Может быть, попробовать, setTimezone():

public function get12HourDateTime($date, $format = 'Y-m-d h:i:s a') 
{ 
    $date = new DateTime($date); 
    $date->setTimezone(new DateTimeZone('America/Chicago')); 

    return $date->format($format) ; 
} 

EDIT

public function get12HourDateTime($date, $format = 'Y-m-d h:i:s a') 
{ 
    $date = new DateTime($date, new DateTimeZone('UTC')); 
    $date->setTimezone(new DateTimeZone('America/Chicago')); 
    return $date->format($format) ; 
} 

Поскольку вы первый хотите инициализировать DateTime с UTC часовой пояс (так что соответствует $date), а затем перенести его соответственно.

+0

Хорошая идея, но это, кажется, не проблема здесь – JasonDavis

+0

В примере кода $ date уже является объектом datetime, поэтому сделать еще один кажется суперплодным. Тем не менее, у меня был такой же базовый ответ - используйте setTimezone – gview

+0

@jasondavis, см. Обновление - кажется, работает - спасибо за предоставление краткого и полного кода :-) – jedwards

0

Вы вызываете один конструктор и каждый раз назначаете часовой пояс, поэтому сначала создается каждый новый объект, созданный этой конструкцией.

public function __construct() 
{ 
    $this->timeZone = new DateTimeZone('UTC'); 
    $this->dateTime = new DateTime(null, $this->timeZone); 
} 

И когда вы используете UNIX TIMESTAMP, который всегда будет возвращаться в часовой пояс UTC.

Смежные вопросы