Creating a timezone form item using Date API

This is simple. Just use the 'date_timezone' type, which is provided by date_api.module.

  $form['timezone'] = array(
    '#type' => 'date_timezone',
    '#default_value' => $timezone,
    '#description' => "Select a timezone if all the events will happen in the same place. Select that place's timezone",
  );

Converting to and from UTC

In the new system you just need to know the timezone name and either the UTC or local time. We store the UTC time and the timezone name in the database (in two separate fields). We retrieve that data and do:

$date = the UTC value from the database
$local_zone = the name of the local timezone
$type = the type of date value, DATE_DATETIME, DATE_ISO, or DATE_UNIX

$date = date_make_date($date, 'UTC', $type);
date_timezone_set($date, timezone_open($local_zone));

$date now contains the local value of the date.
Output it like:

print date_format_date($date, 'custom', 'm/d/Y H:i');

To convert a local date back to UTC to store it in the database, do:

$date = local date value
$local_zone = the name of the local timezone
$type = the type of date value, DATE_DATETIME, DATE_ISO, or DATE_UNIX

$date = date_make_date($date, $local_zone, $type);
date_timezone_set($date, timezone_open('UTC'));

$date now contains the UTC value of the date.
Output it like:

print date_format_date($date, 'custom', 'm/d/Y H:i');

Use of timezone abbreviations

The API doesn't handle timezone abbreviations at all, there's no way to do it right because they are not unique (EST could be Eastern Standard Time or European Summer Time). We need the full, undeprecated timezone name, which looks like 'America/Chicago'. It is comprised of the name of the continent and the major city in the timezone. Older names like 'US/Central' are deprecated because the area names change, but city names rarely do. Some good info about timezones is at http://en.wikipedia.org/wiki/Zoneinfo.

Also, we do not use spaces in the timezone names, so we use America/New_York, not America/New York. The PHP 5.2 date functions and MYSQL native timezone handling all expect names without spaces in them to work correctly.

You can use the php function timezone_name_from_abbr() to try to translate to and from abbreviations, but it's not entirely reliable, as noted above. If we have the current offset and we know if it's currently daylight savings time or not, you can combine that with the abbreviation to get the timezone name, but that's a lot of 'if's.

Timezone Names

The complete list of allowed, undeprecated timezone names is on this page

Comments

ssm2017 Binder’s picture

using d6.15 and date 6.x.2.4
i needed to convert to a timestamp to save to the base and convert it back to user's timezone.
i had a problem using DATE_UNIX, so i am using a string and done like that :

  // First get the user's (or system default) timezone info
  $user_timezone_name = date_default_timezone_name(TRUE);
drupal_set_message('user timezone name = '. $user_timezone_name);

  $text_date = '2010-02-14 07:00:00';
drupal_set_message('start date = '. $text_date);

  // Convert the user entered date into a PHP 5 DateTime object
  $local_date = new DateTime($text_date);

  // Reformat the user entered date into an ISO date that date_make_date() will accept
  $iso_date_string = date_format_date($local_date, 'custom', 'Y-m-d\TH:i:s');
drupal_set_message('iso date_string = '. $iso_date_string);

  // Create a DateTime object with the user's timezone info
  $utc_date = date_make_date($iso_date_string, $user_timezone_name, DATE_DATETIME);

  // Change the timezone to UTC
  date_timezone_set($utc_date, timezone_open('UTC'));

  // Format the UTC version of the DateTime for use in node->save()
  $utc_date_string = date_format_date($utc_date, 'custom', 'Y-m-d\TH:i:s');
drupal_set_message('utc date string = '. $utc_date_string);

  // convert to timestamp
  $timestamp = strtotime($utc_date_string);
drupal_set_message('timestamp = '. $timestamp);

// ============================================

// now, i save it to the database as timestamp

// ============================================

// *************************************************************************************

// ===================================================================================

// and now, i would like to get to from the database as timestamp and convert it back

// ===================================================================================

  // convert back to string
  $new_date = date('Y-m-d\TH:i:s', $timestamp);
drupal_set_message('timestamp converted back = '. $new_date);

  // ok, so now get back to the user timezone
  $type = DATE_DATETIME;

  $new_date = date_make_date($new_date, 'UTC', $type);
  date_timezone_set($new_date, timezone_open($user_timezone_name));
  $back = date_format_date($new_date, 'custom', 'Y-m-d H:i:s');
drupal_set_message('back to the start = '. $back);

and here is the output :

    * user timezone name = Pacific/Tahiti
    * start date = 2010-02-14 07:00:00
    * iso date_string = 2010-02-14T07:00:00
    * utc date string = 2010-02-14T17:00:00
    * timestamp = 1266163200
    * timestamp converted back = 2010-02-14T17:00:00
    * back to the start = 2010-02-14 07:00:00