在AppModel-> afterFind(cakePHP)中转换时区之间的日期

dea*_*_au 5 php timezone datetime cakephp

我有一个cakePHP应用程序,它从两个不同的数据库中提取数据,这些数据库在不同时区的数据中存储日期和时间.一个数据库的时区是Europe/Berlin,而另一个是Australia/Sydney.为了使事情变得更复杂,应用程序托管在美国的服务器上,并且必须在当地时区向最终用户呈现时间.

很容易告诉我必须访问哪个数据库,因此我在我的设置中设置了适当的时区(使用date_default_timezone_set()),beforeFind以便在正确的时区发送带有日期的查询.

我的问题是然后将日期转换afterFind为用户的时区.我通过通过这个时区作为命名参数,并访问这个在我使用的模型Configure::write()Configure.read().这很好用.
问题是它似乎多次应用我的时区转换.例如,如果我Australia/SydneyAustralia/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;                    
}
Run Code Online (Sandbox Code Playgroud)

那么有没有人对转换为何多次发生有任何想法?或者有没有人有更好的方法来转换日期?我显然做错了什么,我只是坚持这是什么.

dea*_*_au 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;
}
Run Code Online (Sandbox Code Playgroud)

作为旁注,我也不再使用该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;                      
}
Run Code Online (Sandbox Code Playgroud)