2010-09-23 4 views
5

У меня есть приложение cakePHP, которое извлекает данные из двух разных баз данных, которые хранят даты и время в своих данных из разных часовых поясов. Часовой пояс одной базы данных - Europe/Berlin, а другой - Australia/Sydney. Чтобы усложнить ситуацию, приложение размещается на сервере в США, а время должно быть представлено конечному пользователю в локальном часовом поясе.Преобразование дат между часовыми поясами в AppModel-> afterFind (cakePHP)

Достаточно просто указать, к какой базе данных я должен получить доступ, и поэтому я установил соответствующий часовой пояс (используя date_default_timezone_set()) в своем beforeFind, чтобы запрос был отправлен с датой в правильном часовом поясе.

Моя проблема заключается в преобразовании дат в afterFind в часовой пояс пользователя. Я передаю этот часовой пояс через именованный параметр, и для доступа к нему в модели я использую Configure::write() и Configure.read(). Это прекрасно работает.
Проблема в том, что она, кажется, применяет мое временное преобразование несколько раз. Например, если я запрашиваю базу данных Australia/Sydney от Australia/Perth, время должно быть на два часа позади, но это выходит за шесть часов. Я попытался повторить время от своей функции до и после их преобразования, и каждое преобразование работало правильно, но оно менялось несколько раз, и я не могу понять, почему.

Методы Я в настоящее время используют (в моем AppModel), чтобы конвертировать из одного часового пояса в другой заключается в следующем:

function afterFind($results, $primary){ 
    // Only bother converting if the local timezone is set. 
    if(Configure::read('TIMEZONE')) 
     $this->replaceDateRecursive($results); 
    return $results; 
} 

function replaceDateRecursive(&$results){ 
    $local_timezone = Configure::read('TIMEZONE'); 

    foreach($results as $key => &$value){ 
     if(is_array($value)){ 
      $this->replaceDateRecursive($value); 
     } 
     else if(strtotime($value) !== false){ 
      $from_timezone = 'Europe/Berlin'; 
      if(/* using the Australia/Sydney database */) 
       $from_timezone = 'Australia/Sydney'; 
      $value = $this->convertDate($value, $from_timezone, $local_timezone, 'Y-m-d H:i:s'); 
     } 
    } 
} 

function convertDate($value, $from_timezone, $to_timezone, $format = 'Y-m-d H:i:s'){ 
    date_default_timezone_set($from_timezone); 
    $value = date('Y-m-d H:i:s e', strtotime($value)); 
    date_default_timezone_set($to_timezone); 
    $value = date($format, strtotime($value)); 

    return $value;      
} 

Так есть ли какие-либо идеи относительно того, почему превращение происходит несколько раз? Или у кого-нибудь есть лучший метод для преобразования дат? Я, очевидно, что-то делаю неправильно, я просто зациклился на том, что это.

+0

Спасибо за этот код, я закончил делать что-то действительно похожее. –

ответ

2

Я разработал решение. Я действительно не понимал, что до сих пор находился параметр $primary в afterFind. Таким образом, чтобы исправить мой код, указанный выше, все, что нужно сделать, это изменить if в afterFind к следующая:

function afterFind($results, $primary){ 
    // Only bother converting if these are the primary results and the local timezone is set. 
    if($primary && Configure::read('TIMEZONE')) 
     $this->replaceDateRecursive($results); 
    return $results; 
} 

Как примечание стороны, я больше не буду с помощью функции date_default_timezone_set() сделать преобразование часового пояса, либо , Моя функция convertDate изменилась следующим образом:

function convertDate($value, $from_timezone, $to_timezone, $format = 'Y-m-d H:i:s'){ 
    $dateTime = new DateTime($value, new DateTimeZone($from_timezone)); 
    $dateTime->setTimezone(new DateTimeZone($to_timezone)); 
    $value = $dateTime->format($format); 

    return $value;      
} 
Смежные вопросы