我有一个cakePHP应用程序,它从两个不同的数据库中提取数据,这些数据库在不同时区的数据中存储日期和时间。一个数据库的时区为Europe/Berlin
,另一个为Australia/Sydney
。为了使事情变得更复杂,应用程序托管在美国的服务器上,并且必须在当地时区向最终用户呈现时间。
告诉我必须访问哪个数据库很容易,因此我在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;
}