Cotonti / Open Source PHP Content Management FrameworkContent Management Framework

Timezone handling in Cotonti

Documentation / Developer Guide / Timezone handling in Cotonti

How Cotonti handles timezones since Siena 0.9.11

Cotonti 0.9.11 introduces a new way of handling timezones. In the past, users could set the timezone offset from GMT in their profile, meaning users living in Central Europe would set their timezone to GMT+1. The new timezone system implemented in Cotonti 0.9.11 no longer stores a timezone offset, but a timezone identifier. A timezone identifier is a string composed of a continent and a city, and can be one of the timezones supported by PHP. This means that instead of setting the timezone offset such as GMT+1 in your profile, you’d set a more specific timezone such as Europe/Amsterdam.

The reason for the migration from timezone offsets to timezone identifiers is the support for Daylight Saving Time (DST). In the past, Cotonti would always show times based on the timezone offset from a user’s profile, which resulted in incorrect times during DST. Clocks would be off by one hour in the summer. With the new system, Cotonti will automatically adjust times if DST is in effect. Since the dates at which DST starts and ends vary between countries and timezones, the only reliable way to determine whether or not to apply DST is to use PHP’s built-in timezone functions, which use the internal database of timezone transitions (DST changes) provided by the server operating system.

#1. Automatic migration

When upgrading your Cotonti installation to Siena 0.9.11, you may notice that your cot_users database table is modified to meet the new timezone system. The old timezone offset is automatically converted to a timezone identifier, based on the user’s country. For example, a user with timezone offset GMT+1 and country code ‘nl’ (Netherlands) will be migrated to the Europe/Amsterdam timezone identifier. On the other hand, a user from Germany (‘de’) with the same timezone offset will be migrated to Europe/Berlin. If the country and offset do not match the timezone will be set to GMT. Users which have not set a timezone offset or country will also be migrated to GMT, since it’s the default.

The new timezone system comes with a new list of timezone options in your profile. Since there are many timezones with the same GMT offset, the list is a lot longer. To keep it clear, timezone identifier is prepended with the GMT offset (without DST). For example, the option for Amsterdam looks like “GMT+01:00 Europe/Amsterdam”.

#2. Function reference

For developers, the new timezone system introduces several helper functions. Here’s an overview:

cot_selectbox_timezone($chosen, $name, $add_gmt = true, $dst = false, $attrs = '', $custom_rc = '')
Returns timezone selection dropdown. Part of Forms API.
Example: cot_selectbox_timezone('GMT', ‘rtimezone’) =>

<select name="rtimezone">
  <option value="GMT" selected="selected">GMT</option>
  <option value="Pacific/Apia">GMT-11:00 Pacific/Apia</option>

cot_build_timezone($offset, $withgmt = true, $short = false)
Returns timezone offset formatted according to ISO 8601.
Example: cot_build_timezone(3600) =>


cot_timezone_list($withgmt = false, $dst = false)
Returns a list of timezones sorted by GMT offset.
Example: cot_timezone_list() =>

    'name' => "Pacific/Apia",
    'offset' => -39600,
    'description' => "GMT-11:00 Pacific/Apia"
    'name' => "Pacific/Midway",
    'offset' => -39600,
    'description' => "GMT-11:00 Pacific/Midway"

cot_timezone_offset($tz, $hours = false, $dst = true)
Returns the offset from GMT in seconds or hours, with or without DST.
Example: cot_timezone_offset("Europe/Amsterdam") =>

3600 (winter) or 7200 (summer)

cot_timezone_search($countrycode = '', $gmtoffset = null)
Returns a list of possible timezones based on country and/or GMT offset.
Example: cot_timezone_search("ru", 14400) =>


Returns previous, current and next transition in a certain timezone. Useful for detecting if DST is currently in effect.
Example: cot_timezone_transitions("Europe/Amsterdam") =>

  'previous' => array(
    'ts' => 1319936400,
    'time' => "2011-10-30T01:00:00+0000",
    'offset' => 3600,
    'isdst' => false,
    'abbr' => "CET"
  'current' => array(
    'ts' => 1332637200,
    'time' => "2012-03-25T01:00:00+0000",
    'offset' => 7200,
    'isdst' => true,
    'abbr' => "CEST"
  'next' => array(
    'ts' => 1351386000,
    'time' => "2012-10-28T01:00:00+0000",
    'offset' => 3600,
    'isdst' => false,
    'abbr' => "CET"

No comments yet
Only registered users can post new comments