Zend_Db: Setting MySQL's timezone per connection
I have a Linux server with a system timezone of ET (US/Eastern). But I also have a web application that needs to run in a timezone of PT (US/Pacific). Of course that's not a problem at all. I just set the timezone in my web application's bootstrap:
date_default_timezone_set('America/Los_Angeles'); // Pacific timezone
Now I have another problem; the database. Sometimes I use PHP to generate dates such as date('Y-m-d H:i:s', strtotime('-2 minutes')). Other times I insert records and use new Zend_Db_Expr('NOW()');. But because MySQL isn't aware that I'd like to use pacific time, dates end up being inconsistent and are off by three hour.
It's a fairly easy fix, though, with a bit of logic added to a custom MySQL database adapter:
<?php
/**
* @see Zend_Db_Adapter_Pdo_Mysql
*/
require_once 'Zend/Db/Adapter/Pdo/Mysql.php';
/**
* MySQL PDO adapter extended to set the timezone
*/
class My_Db_Adapter_Pdo_Mysql extends Zend_Db_Adapter_Pdo_Mysql
{
/**
* @var bool
*/
protected $_initialized = false;
/**
* Connects to the database.
*
*/
protected function _connect()
{
parent::_connect();
if (!$this->_initialized) {
$this->_initialized = true;
if ($this->_config['timezone']) {
// Requires PHP 5.2+
$dtz = new DateTimeZone($this->_config['timezone']);
$offset = $dtz->getOffset(new DateTime('NOW')) / 60 / 60;
$this->query(sprintf("SET time_zone = '%d:00'", $offset));
}
}
}
}
To kick this all off my bootstrap contains:
$config = array();
$config['host'] = 'localhost';
$config['username'] = 'username';
$config['password'] = 'password';
$config['dbname'] = 'mydatabase';
$config['timezone'] = 'America/Los_Angeles';
$config['adapterNamespace'] = 'My_Db_Adapter';
$db = Zend_Db::factory('PDO_MYSQL', $config);
Zend_Db_Table::setDefaultAdapter($db);
date_default_timezone_set('America/Los_Angeles');
And now I am free to continue my habit of inconsistency when specifying dates.
Print This Post
September 27th, 2010 - 09:30
Hi Marcus
I ran into the very same problem and was lucky to find your howto on this topic. While reading documentations on the MySQL and ZF websites I found out that it is possible to pass driver options which allow the setting of the timezone. A simple entry like
database.params.driver_options.MYSQLI_INIT_COMMAND = "set time_zone = '+2:00'"
in the config will handle the setting of the timezone as wished. This works with the current ZF version 1.10.8.
Thanks and Greetings
Dominik
October 18th, 2010 - 20:53
Dominik, indeed recent versions of Zend Framework support this out of the box. That wasn't the case two years ago.
September 19th, 2011 - 17:57
Is there a PostgreSQL equivalent of this?
July 11th, 2011 - 14:43
Won't this break for timezones with non-whole numbers? Try for instance Pacific/Chatham. It should be +10.45.
I used this:
$minutes = $timezone->getOffset(new DateTime('NOW')) / 60;
$offset = sprintf("SET time_zone = '%d:%2d'", $minutes / 60, $minutes % 60);
January 26th, 2012 - 23:42
Thanks, Dominic!
Very interesting!