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

标签 php datetime cakephp timezone

我有一个 cakePHP 应用程序,它从两个不同的数据库中提取数据,这两个数据库将日期和时间存储在来自不同时区的数据中。一个数据库的时区是 Europe/Berlin,另一个是 Australia/Sydney。让事情变得更复杂的是,该应用程序托管在美国的服务器上,并且必须以本地时区向最终用户显示时间。

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

然后我的问题是将 afterFind 中的日期转换为用户的时区。我将这个时区作为命名参数传递,并在我使用 Configure::write()Configure.read() 的模型中访问它。这很好用。
问题是它似乎多次应用我的时区转换。例如,如果我从 Australia/Perth 查询 Australia/Sydney 数据库,时间应该晚了两个小时,但结果却晚了六个小时。我尝试在转换之前和之后从我的函数中回显时间,并且每次转换都正常工作,但它不止一次转换时间,我不明白为什么。

我目前使用的(在我的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;                    
}

那么有人知道为什么会多次发生转换吗?或者有没有人有更好的方法来转换日期?我显然做错了什么,我只是不知道那是什么。

最佳答案

我想出了一个解决方案。直到现在我才真正明白 afterFind 中的 $primary 参数是干什么用的。所以要修复上面的代码,我所要做的就是将 afterFind 中的 if 更改为以下内容:

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;                      
}

关于php - 在 AppModel->afterFind (cakePHP) 中转换时区之间的日期,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3775038/

相关文章:

php - 如何在脚本中获取包名?

php - 快速手册 PHP 开发工具包

PHP:字符串中的变量没有连接

java - Java 有没有支持一年中的季度和星期的 DateTime 库?

javascript - 使用 Date.UTC 转换时返回日期时间的正确月份

validation - Cakephp 3.x 自定义验证规则的创建和使用

php - 垂直显示列和行

python - 如何在 Python 中找到从周日开始的周数?

php - 将 INSERT IGNORE 语句添加到 CAKEPHP saveAll 方法

PHP MySQL - 如何按计算字段对分页结果进行排序?