User Timezones in CakePHP

Hello Again,
For anybody who has built a user based website, no doubt you’ve come across the issues with timezones.
Obviously, all information stored in our databases are saved using the same timezone. Therefore what happens when users sign up that are in different timezones to your server? Luckily, once again the guys from CakePHP make this very easy for us to modify timezones.
Now first of all, the user needs to specify which timezone they are in. First, create another field in your Users Table.
1ALTER TABLE users ADD timezone DECIMAL(5,1);
We’ve now got somewhere that you users can save their timezones. Now, we’ve got to give our users the list of timezones to choose from, heres a quick helper I put together to make it easy for you.
123456789101112131415161718192021222324252627282930313233343536373839404142434445class TimeZoneHelper extends AppHelper {
    public $helpers = array('Form');
    function select($field, $selected, $label, $attributes = array(), $showEmpty = false) {

    $timezones = array(
    '-12' => '(GMT -12:00 hours) Eniwetok, Kwajalein',
    '-11' => '(GMT -11:00 hours) Midway Island, Somoa',
    '-10' => '(GMT -10:00 hours) Hawaii',
    '-9' => '(GMT -9:00 hours) Alaska',
    '-8' => '(GMT -8:00 hours) Pacific Time (US & Canada)',
    '-7' => '(GMT -7:00 hours) Mountain Time (US & Canada)',
    '-6' => '(GMT -6:00 hours) Central Time (US & Canada), Mexico City',
    '-5' => '(GMT -5:00 hours) Eastern Time (US & Canada), Bogota, Lima, Quito',
    '-4' => '(GMT -4:00 hours) Atlantic Time (Canada), Caracas, La Paz',
    '-3.5' => '(GMT -3:30 hours) Newfoundland',
    '-3' => '(GMT -3:00 hours) Brazil, Buenos Aires, Georgetown',
    '-2' => '(GMT -2:00 hours) Mid-Atlantic',
    '-1' => '(GMT -1:00 hours) Azores, Cape Verde Islands',
    '0' => '(GMT) Western Europe Time, London, Lisbon, Casablanca, Monrovia',
    '+1' => '(GMT +1:00 hours) CET(Central Europe Time), Brussels, Copenhagen, Madrid, Paris',
    '+2' => '(GMT +2:00 hours) EET(Eastern Europe Time), Kaliningrad, South Africa',
    '+3' => '(GMT +3:00 hours) Baghdad, Kuwait, Riyadh, Moscow, St. Petersburg, Volgograd, Nairobi',
    '+3.5' => '(GMT +3:30 hours) Tehran',
    '+4' => '(GMT +4:00 hours) Abu Dhabi, Muscat, Baku, Tbilisi',
    '+4.5' => '(GMT +4:30 hours) Kabul',
    '+5' => '(GMT +5:00 hours) Ekaterinburg, Islamabad, Karachi, Tashkent',
    '+5.5' => '(GMT +5:30 hours) Bombay, Calcutta, Madras, New Delhi',
    '+6' => '(GMT +6:00 hours) Almaty, Dhaka, Colombo',
    '+7' => '(GMT +7:00 hours) Bangkok, Hanoi, Jakarta',
    '+8' => '(GMT +8:00 hours) Beijing, Perth, Singapore, Hong Kong, Chongqing, Urumqi, Taipei',
    '+9' => '(GMT +9:00 hours) Tokyo, Seoul, Osaka, Sapporo, Yakutsk',
    '+9.5' => '(GMT +9:30 hours) Adelaide, Darwin',
    '+10' => '(GMT +10:00 hours) EAST(East Australian Standard), Guam, Papua New Guinea, Vladivostok',
    '+11' => '(GMT +11:00 hours) Magadan, Solomon Islands, New Caledonia',
    '+12' => '(GMT +12:00 hours) Auckland, Wellington, Fiji, Kamchatka, Marshall Island'   
    );
   
    $list = '';
    $list .= $this->Form->label($field, $label);
    $list .= $this->Form->select($field, $timezones, $selected, $attributes, $showEmpty);
   
   
    return $this->output($list);
    }
}
Next, you just add Timezone’ to your helper array inside your controller.
To use the helper, its very simple, just place it in your Add/Edit (or anywhere in your views for that matter) views. Here’s an example below:
1echo $timeZone->select('timezone', '+10', 'Please select your Timezone');
Ok, so now the user has successfully selected their preferred timezone.
The next part of this problem is changing the formatted time in the view to match the timezone that the user has selected.
If you have a table such as blog, posts, articles etc, no doubt you have taken advantage of CakePHP’s automagic created’ and modified’ fields, which will automatically insert the current date, So you’ll end up with something like 2009-07-21 15:04:25′. That doesn’t look too presentable now does it?
Using CakePHP’s Time’ helper (make sure you add it to your $helpers array in your controller), we can format the date stored in the database into something much more presentable. For example,
1echo $time->format('M d, Y', $post['created']);
… will return Jul 21, 2009′, looks much better right? Now all we need to do is add our GMT timezone.
Make sure you’ve got the correct associations setup between your tables, so you can access your user data.
1echo $time->format('M d, Y', $post['created'], null, $auth['User']['timezone']);
If you have a look the TimeHelper info in the CakePHP API, you’ll see in a lot of the methods, there is a $userOffset parameter, which will allow you to change the GMT offset. In the above example I used $auth, it’s just a variable that is set from the controller that checks authentication.
1$this->set('auth', $this->Auth->user);
So there we have it, if you see a way to improve the code I have written, feel free to post a comment and let me know.
EDIT: I made a mistake when using the $userOffset parameter, if you call $post['User']['timezone']; it will change the timezone depending on the user who posted it, not the user logged in. This has been fixed.