I have a cakePHP application that is pulling data from two different databases, which store dates and times in their data from different timezones. One database's timezone is Europe/Berlin
, and the other's is Australia/Sydney
. To make things more complicated, the application is hosted on a server in the US, and times must be presented to the end user in their local timezone.
It's easy enough to tell which database I have to access, and so I set the appropriate timezone (using date_default_timezone_set()
) in my beforeFind
so that the query is sent with a date in the correct timezone.
My problem is then converting the dates in the afterFind
to the timezone of the user. I'm passing this timezone through as a named parameter, and to access this in the model I'm using Configure::write()
and Configure.read()
. This works fine.
The problem is that it seems to be applying my timezone conversion multiple times. For example, if I'm querying the Australia/Sydney
database from Australia/Perth
the time should be two hours behind, but it's coming out as six hours behind. I tried echoing the times from my function before and after converting them, and each conversion was working correctly, but it was converting the times more than once, and I can't figure out why.
The methods I am currently using (in my AppModel
) to convert from one timezone to another is as follows:
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;
}
So does anyone have any ideas as to why the conversion is happening multiple times? Or does anyone have a better method for converting the dates? I'm obviously doing something wrong, I'm just stuck as to what that is.
I worked out a solution. I didn't really understand what the $primary
parameter in the afterFind
was for until now. So to fix my code above, all I have to do is change the if
in the afterFind
to the following:
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;
}
As a side note, I am no longer using the date_default_timezone_set()
function to do the timezone conversion, either. My convertDate
function has changed as follows:
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;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With