Index: CHANGELOG.txt =================================================================== RCS file: /cvs/drupal/drupal/CHANGELOG.txt,v retrieving revision 1.285 diff -u -p -r1.285 CHANGELOG.txt --- CHANGELOG.txt 2 Nov 2008 10:52:53 -0000 1.285 +++ CHANGELOG.txt 2 Nov 2008 23:32:56 -0000 @@ -37,6 +37,16 @@ Drupal 7.0, xxxx-xx-xx (development vers * Added support for language-aware searches. - Testing: * Added test framework and tests. +- Improved time zone support: + * Drupal now uses PHP's time zone database when rendering dates in local + time. Site-wide and user-configured time zone offsets have been converted + to time zone names, e.g. Africa/Abidjan. + * In some cases the upgrade and install scripts do not choose the preferred + site default time zone. The automatically-selected time zone can be + corrected at admin/settings/date-time. + * If your site is being upgraded from Drupal 6 and you do not have the + contributed date or event modules installed, user time zone settings will + have to be reconfigured by each user. - Removed ping module: * Contributed modules with similar functionality are available. - Refactored the "access rules" component of user module: Index: install.php =================================================================== RCS file: /cvs/drupal/drupal/install.php,v retrieving revision 1.138 diff -u -p -r1.138 install.php --- install.php 29 Oct 2008 10:08:51 -0000 1.138 +++ install.php 2 Nov 2008 23:32:56 -0000 @@ -1077,7 +1077,7 @@ function install_configure_form(&$form_s $form['server_settings']['date_default_timezone'] = array( '#type' => 'select', '#title' => st('Default time zone'), - '#default_value' => 0, + '#default_value' => date_default_timezone_get(), '#options' => _system_zonelist(), '#description' => st('By default, dates in this site will be displayed in the chosen time zone.'), '#weight' => 5, Index: includes/common.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/common.inc,v retrieving revision 1.815 diff -u -p -r1.815 common.inc --- includes/common.inc 1 Nov 2008 21:21:34 -0000 1.815 +++ includes/common.inc 2 Nov 2008 23:41:10 -0000 @@ -1282,7 +1282,7 @@ function format_interval($timestamp, $gr * before a character to avoid interpreting the character as part of a date * format. * @param $timezone - * Time zone offset in seconds; if omitted, the user's time zone is used. + * Time zone identifier; if omitted, the user's time zone is used. * @param $langcode * Optional language code to translate to a language other than what is used * to display the page. @@ -1290,17 +1290,21 @@ function format_interval($timestamp, $gr * A translated date string in the requested format. */ function format_date($timestamp, $type = 'medium', $format = '', $timezone = NULL, $langcode = NULL) { + static $timezones = array(); if (!isset($timezone)) { global $user; - if (variable_get('configurable_timezones', 1) && $user->uid && strlen($user->timezone)) { + if (variable_get('configurable_timezones', 1) && $user->uid && $user->timezone) { $timezone = $user->timezone; } else { - $timezone = variable_get('date_default_timezone', 0); + $timezone = variable_get('date_default_timezone', 'UTC'); } } - - $timestamp += $timezone; + // Store DateTimeZone objects in an array rather than repeatedly + // contructing identical objects over the life of a request. + if (!isset($timezones[$timezone])) { + $timezones[$timezone] = timezone_open($timezone); + } switch ($type) { case 'small': @@ -1319,28 +1323,27 @@ function format_date($timestamp, $type = $max = strlen($format); $date = ''; + // Create a DateTime object from the timestamp. + $date_time = date_create('@' . $timestamp); + // Set the time zone for the DateTime object. + date_timezone_set($date_time, $timezones[$timezone]); + for ($i = 0; $i < $max; $i++) { $c = $format[$i]; - if (strpos('AaDlM', $c) !== FALSE) { - $date .= t(gmdate($c, $timestamp), array(), $langcode); + if (strpos('AaeDlMT', $c) !== FALSE) { + $date .= t(date_format($date_time, $c), array(), $langcode); } elseif ($c == 'F') { // Special treatment for long month names: May is both an abbreviation // and a full month name in English, but other languages have // different abbreviations. - $date .= trim(t('!long-month-name ' . gmdate($c, $timestamp), array('!long-month-name' => ''), $langcode)); + $date .= trim(t('!long-month-name ' . date_format($date_time, $c), array('!long-month-name' => ''), $langcode)); } - elseif (strpos('BdgGhHiIjLmnsStTUwWYyz', $c) !== FALSE) { - $date .= gmdate($c, $timestamp); + elseif (strpos('BcdGgHhIijLmNnOoPSstUuWwYyZz', $c) !== FALSE) { + $date .= date_format($date_time, $c); } elseif ($c == 'r') { - $date .= format_date($timestamp - $timezone, 'custom', 'D, d M Y H:i:s O', $timezone, $langcode); - } - elseif ($c == 'O') { - $date .= sprintf('%s%02d%02d', ($timezone < 0 ? '-' : '+'), abs($timezone / 3600), abs($timezone % 3600) / 60); - } - elseif ($c == 'Z') { - $date .= $timezone; + $date .= format_date($timestamp, 'custom', 'D, d M Y H:i:s O', $timezone, $langcode); } elseif ($c == '\\') { $date .= $format[++$i]; Index: includes/form.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/form.inc,v retrieving revision 1.300 diff -u -p -r1.300 form.inc --- includes/form.inc 2 Nov 2008 06:26:33 -0000 1.300 +++ includes/form.inc 2 Nov 2008 23:32:56 -0000 @@ -1716,7 +1716,7 @@ function date_validate($form) { * Helper function for usage with drupal_map_assoc to display month names. */ function map_month($month) { - return format_date(gmmktime(0, 0, 0, $month, 2, 1970), 'custom', 'M', 0); + return format_date(gmmktime(0, 0, 0, $month, 2, 1970), 'custom', 'M', 'UTC'); } /** Index: modules/system/system.admin.inc =================================================================== RCS file: /cvs/drupal/drupal/modules/system/system.admin.inc,v retrieving revision 1.102 diff -u -p -r1.102 system.admin.inc --- modules/system/system.admin.inc 16 Oct 2008 20:23:08 -0000 1.102 +++ modules/system/system.admin.inc 2 Nov 2008 23:42:53 -0000 @@ -1567,19 +1567,11 @@ function system_date_time_settings() { $form['locale']['date_default_timezone'] = array( '#type' => 'select', '#title' => t('Default time zone'), - '#default_value' => variable_get('date_default_timezone', 0), + '#default_value' => variable_get('date_default_timezone', date_default_timezone_get()), '#options' => $zones, '#description' => t('Select the default site time zone.') ); - $form['locale']['configurable_timezones'] = array( - '#type' => 'radios', - '#title' => t('User-configurable time zones'), - '#default_value' => variable_get('configurable_timezones', 1), - '#options' => array(t('Disabled'), t('Enabled')), - '#description' => t('When enabled, users can set their own time zone and dates will be displayed accordingly.') - ); - $form['locale']['date_first_day'] = array( '#type' => 'select', '#title' => t('First day of week'), @@ -1588,6 +1580,35 @@ function system_date_time_settings() { '#description' => t('The first day of the week for calendar views.') ); + $form['timezone'] = array( + '#type' => 'fieldset', + '#title' => t('Time zone handling'), + ); + + $form['timezone']['configurable_timezones'] = array( + '#type' => 'radios', + '#title' => t('User-configurable time zones'), + '#default_value' => variable_get('configurable_timezones', 1), + '#options' => array(t('Disabled'), t('Enabled')), + '#description' => t('When enabled, users can set their own time zone and dates will be displayed accordingly.') + ); + + $form['timezone']['user_default_timezone'] = array( + '#type' => 'radios', + '#title' => t('User time zone defaults'), + '#default_value' => variable_get('user_default_timezone', 0), + '#options' => array(t('New users will be set to the default time zone at registration.'), t('New users will get an empty time zone at registration.'), t('New users will select their own time zone at registration.')), + '#description' => t('Method for setting user time zones at registration when user-configurable time zones are enabled. This only affects the initial time zone setting for a new registration, users will be able to change their time zone any time they edit their account.') + ); + + $form['timezone']['empty_timezone_message'] = array( + '#type' => 'radios', + '#title' => t('Empty user time zones'), + '#default_value' => variable_get('empty_timezone_message', 0), + '#options' => array(t('Ignore empty user time zones.'), t('Remind users at login if their time zone is not set.')), + '#description' => t('Handling for empty user time zones when user-configurable time zones are enabled. Use this option to help ensure that users set the correct time zone.') + ); + $form['date_formats'] = array( '#type' => 'fieldset', '#title' => t('Formatting'), Index: modules/system/system.install =================================================================== RCS file: /cvs/drupal/drupal/modules/system/system.install,v retrieving revision 1.275 diff -u -p -r1.275 system.install --- modules/system/system.install 2 Nov 2008 17:56:20 -0000 1.275 +++ modules/system/system.install 3 Nov 2008 00:12:19 -0000 @@ -3115,6 +3115,37 @@ function system_update_7012() { } /** + * Convert default time zone offset to default time zone name. + */ +function system_update_7013() { + $ret = array(); + // If the contributed Date module set a default time zone name, use + // this setting as the default time zone. + if ($timezone = variable_get('date_default_timezone_name', NULL)) { + variable_set('date_default_timezone', $timezone); + } + // If the contributed Event module has set a default site time zone + // use that information. + elseif ($timezone_id = variable_get('date_default_timezone_id', 0)) { + $timezone = db_result(db_query('SELECT name FROM {event_timezone} t WHERE t.timezone = :timezone_id', array(':timezone_id' => $timezone_id))); + $timezone = str_replace(' ', '_', $timezone); + variable_set('date_default_timezone', $timezone); + } + // If the previous default time zone was a non-zero offset, guess the + // site's intended time zone based on that offset and the server's + // daylight saving time status. + elseif ($timezone = variable_get('date_default_timezone', 0)) { + variable_set('date_default_timezone', timezone_name_from_abbr('', intval($timezone), intval(date('I')))); + } + // Otherwise, set the default time zone to UTC. + else { + variable_set('date_default_timezone', 'UTC'); + } + drupal_set_message(t('The default time zone has been set to %timezone. Please check the date and time configuration page to configure it correctly.', array('%timezone' => variable_get('date_default_timezone', 'UTC'), '!date-settings' => url('admin/settings/date-time'))), 'warning'); + return $ret; +} + +/** * @} End of "defgroup updates-6.x-to-7.x" * The next series of updates should start at 8000. */ Index: modules/system/system.js =================================================================== RCS file: /cvs/drupal/drupal/modules/system/system.js,v retrieving revision 1.16 diff -u -p -r1.16 system.js --- modules/system/system.js 29 Oct 2008 10:01:27 -0000 1.16 +++ modules/system/system.js 2 Nov 2008 23:57:27 -0000 @@ -117,3 +117,53 @@ Drupal.behaviors.dateTime = { $('select.date-format', context).trigger('change'); } }; + +/** + * Set the client's system time zone as default values of form fields. + */ +Drupal.setDefaultTimezone = function() { + var dateString = Date(); + // In some client environments, date strings include a time zone + // abbreviation, between 3 and 5 letters enclosed in parentheses, + // which can be interpreted by PHP. + var matches = dateString.match(/\(([A-Z]{3,5})\)/); + var abbreviation = matches ? matches[1] : 0; + + // For all other client environments, the abbreviation is set to "0" + // and the current offset from UTC and daylight saving time status are + // used to guess the time zone. + var dateNow = new Date(); + var offsetNow = dateNow.getTimezoneOffset() * -60; + + // Use January 1 and July 1 as test dates for determining daylight + // saving time status by comparing their offsets. + var dateJan = new Date(dateNow.getFullYear(), 0, 1, 12, 0, 0, 0); + var dateJul = new Date(dateNow.getFullYear(), 6, 1, 12, 0, 0, 0); + var offsetJan = dateJan.getTimezoneOffset() * -60; + var offsetJul = dateJul.getTimezoneOffset() * -60; + + // If the offset from UTC is identical on January 1 and July 1, + // assume daylight saving time is not used in this time zone. + if (offsetJan == offsetJul) { + var isDaylightSavingTime = ''; + } + // If the maximum annual offset is equivalent to the current offset, + // assume daylight saving time is in effect. + else if (Math.max(offsetJan, offsetJul) == offsetNow) { + var isDaylightSavingTime = 1; + } + // Otherwise, assume daylight saving time is not in effect. + else { + var isDaylightSavingTime = 0; + } + + // Submit request to the system/timezone callback and set the form field + // to the response time zone. + var path = 'system/timezone/' + abbreviation + '/' + offsetNow + '/' + isDaylightSavingTime; + // The client date is passed to the callback for debugging purposes. + $.getJSON(Drupal.settings.basePath, {q: path, date: dateString}, function(data) { + if (data) { + $("#edit-date-default-timezone, #edit-timezone").val(data); + } + }); +}; Index: modules/system/system.module =================================================================== RCS file: /cvs/drupal/drupal/modules/system/system.module,v retrieving revision 1.635 diff -u -p -r1.635 system.module --- modules/system/system.module 31 Oct 2008 02:18:22 -0000 1.635 +++ modules/system/system.module 3 Nov 2008 00:01:28 -0000 @@ -357,6 +357,12 @@ function system_menu() { 'access callback' => TRUE, 'type' => MENU_CALLBACK, ); + $items['system/timezone'] = array( + 'title' => 'Time zone', + 'page callback' => 'system_timezone', + 'access callback' => TRUE, + 'type' => MENU_CALLBACK, + ); $items['admin'] = array( 'title' => 'Administer', 'access arguments' => array('access administration pages'), @@ -592,7 +598,7 @@ function system_menu() { ); $items['admin/settings/date-time'] = array( 'title' => 'Date and time', - 'description' => "Settings for how Drupal displays date and time, as well as the system's default timezone.", + 'description' => "Settings for how Drupal displays date and time, as well as the system's default time zone.", 'page callback' => 'drupal_get_form', 'page arguments' => array('system_date_time_settings'), 'access arguments' => array('administer site configuration'), @@ -737,29 +743,68 @@ function system_preprocess_page(&$variab function system_user_form(&$edit, &$user, $category = NULL) { if ($category == 'account') { $form['theme_select'] = system_theme_select_form(t('Selecting a different theme will change the look and feel of the site.'), isset($edit['theme']) ? $edit['theme'] : NULL, 2); - if (variable_get('configurable_timezones', 1)) { - $zones = _system_zonelist(); + system_user_timezone($edit, $form); + } + return $form; + } +} + +/** + * Implementation of hook_user_register(). + */ +function system_user_register(&$edit, &$user, $category = NULL) { + if (variable_get('configurable_timezones', 1)) { + $form = array(); + if (variable_get('user_default_timezone', 0) < 2) { $form['timezone'] = array( - '#type' => 'fieldset', - '#title' => t('Locale settings'), - '#weight' => 6, - '#collapsible' => TRUE, - ); - $form['timezone']['timezone'] = array( - '#type' => 'select', - '#title' => t('Time zone'), - '#default_value' => strlen($edit['timezone']) ? $edit['timezone'] : variable_get('date_default_timezone', 0), - '#options' => $zones, - '#description' => t('Select your current local time. Dates and times throughout this site will be displayed using this time zone.'), + '#type' => 'hidden', + '#value' => variable_get('user_default_timezone', 0) == 0 ? variable_get('date_default_timezone', '') : '', ); } - + else { + system_user_timezone($edit, $form); + } return $form; } } /** + * Implementation of hook_user_login(). + */ +function system_user_login(&$edit, &$user, $category = NULL) { + // If the user has a NULL time zone, notify them to set a time zone. + if (!$user->timezone && variable_get('configurable_timezones', 1) && variable_get('empty_timezone_message', 0)) { + drupal_set_message(t('Please configure your account time zone setting.', array('!user-edit' => url("user/$user->uid/edit", array('query' => drupal_get_destination(), 'fragment' => 'edit-timezone'))))); + } +} + +/** + * Add the time zone field to the user edit and register forms. + */ +function system_user_timezone(&$edit, &$form) { + global $user; + $form['timezone'] = array( + '#type' => 'fieldset', + '#title' => t('Locale settings'), + '#weight' => 6, + '#collapsible' => TRUE, + ); + $form['timezone']['timezone'] = array( + '#type' => 'select', + '#title' => t('Time zone'), + '#default_value' => $edit['timezone'] ? $edit['timezone'] : ($edit['uid'] == $user->uid ? variable_get('date_default_timezone', '') : ''), + '#options' => _system_zonelist(($edit['uid'] != $user->uid)), + '#description' => t('Select your current local time. Dates and times throughout this site will be displayed using this time zone.'), + ); + if (!$edit['timezone'] && $edit['uid'] == $user->uid) { + $form['timezone']['#description'] = t('Your time zone setting will be automatically detected if possible. Please confirm the selection and click save.'); + drupal_add_js(drupal_get_path('module', 'system') . '/system.js'); + drupal_add_js('$(Drupal.setDefaultTimezone);', 'inline'); + } +} + +/** * Implementation of hook_block(). * * Generate a block with a promotional link to Drupal.org. @@ -2060,14 +2105,20 @@ function system_block_ip_action() { /** * Generate an array of time zones and their local time&date. + * + * @param $blank + * If evaluates true, prepend an empty time zone option to the array. */ -function _system_zonelist() { - $timestamp = REQUEST_TIME; - $zonelist = array(-11, -10, -9.5, -9, -8, -7, -6, -5, -4, -3.5, -3, -2, -1, 0, 1, 2, 3, 3.5, 4, 5, 5.5, 5.75, 6, 6.5, 7, 8, 9, 9.5, 10, 10.5, 11, 11.5, 12, 12.75, 13, 14); - $zones = array(); - foreach ($zonelist as $offset) { - $zone = $offset * 3600; - $zones[$zone] = format_date($timestamp, 'custom', variable_get('date_format_long', 'l, F j, Y - H:i') . ' O', $zone); +function _system_zonelist($blank = NULL) { + $zonelist = timezone_identifiers_list(); + $zones = $blank ? array('' => t('- None selected -')) : array(); + foreach ($zonelist as $zone) { + // Because many time zones exist in PHP only for backward compatibility + // reasons and should not be used, the list is filtered by a regular + // expression. + if (preg_match('!^((Africa|America|Antarctica|Arctic|Asia|Atlantic|Australia|Europe|Indian|Pacific)/|UTC$)!', $zone)) { + $zones[$zone] = t('@zone: @date', array('@zone' => t($zone), '@date' => format_date(REQUEST_TIME, 'custom', variable_get('date_format_long', 'l, F j, Y - H:i') . ' O', $zone))); + } } return $zones; } @@ -2099,6 +2150,22 @@ function system_check_http_request() { } /** + * Menu callback. Retrieve a JSON object containing a suggested time zone name. + */ +function system_timezone($abbreviation = '', $offset = -1, $is_daylight_saving_time = NULL) { + // An abbreviation of "0" passed in the callback arguments should be + // interpreted as the empty string. + $abbreviation = $abbreviation ? $abbreviation : ''; + $timezone = timezone_name_from_abbr($abbreviation, intval($offset), $is_daylight_saving_time); + // The client date is passed in for debugging purposes. + $date = isset($_GET['date']) ? $_GET['date'] : ''; + // Log a debug message. + watchdog('timezone', 'Detected time zone: %timezone; client date: %date; abbreviation: %abbreviation; offset: %offset; daylight saving time: %is_daylight_saving_time.', array('%timezone' => $timezone, '%date' => $date, '%abbreviation' => $abbreviation, '%offset' => $offset, '%is_daylight_saving_time' => $is_daylight_saving_time)); + drupal_json($timezone); + exit; +} + +/** * Format the Powered by Drupal text. * * @ingroup themeable Index: modules/system/system.test =================================================================== RCS file: /cvs/drupal/drupal/modules/system/system.test,v retrieving revision 1.23 diff -u -p -r1.23 system.test --- modules/system/system.test 1 Nov 2008 21:21:35 -0000 1.23 +++ modules/system/system.test 2 Nov 2008 23:32:57 -0000 @@ -469,6 +469,47 @@ class PageNotFoundTestCase extends Drupa } } +class DateTimeTestCase extends DrupalWebTestCase { + /** + * Implementation of getInfo(). + */ + function getInfo() { + return array( + 'name' => t('Date and time'), + 'description' => t('Configure date and time settings. Test date formatting and time zone handling, including daylight saving time.'), + 'group' => t('System'), + ); + } + + function testDateTime() { + // Setup date/time settings for Honolulu time. + variable_set('date_default_timezone', 'Pacific/Honolulu'); + variable_set('configurable_timezones', 0); + variable_set('date_format_medium', 'Y-m-d H:i:s O'); + + // Create some nodes with different authored-on dates. + $date1 = '2007-01-31 21:00:00 -1000'; + $date2 = '2007-07-31 21:00:00 -1000'; + $node1 = $this->drupalCreateNode(array('created' => strtotime($date1), 'type' => 'article')); + $node2 = $this->drupalCreateNode(array('created' => strtotime($date2), 'type' => 'article')); + + // Confirm date format and time zone. + $this->drupalGet("node/$node1->nid"); + $this->assertText('2007-01-31 21:00:00 -1000', 'Date should be identical, with GMT offset of -10 hours.'); + $this->drupalGet("node/$node2->nid"); + $this->assertText('2007-07-31 21:00:00 -1000', 'Date should be identical, with GMT offset of -10 hours.'); + + // Set time zone to Los Angeles time. + variable_set('date_default_timezone', 'America/Los_Angeles'); + + // Confirm date format and time zone. + $this->drupalGet("node/$node1->nid"); + $this->assertText('2007-01-31 23:00:00 -0800', 'Date should be two hours ahead, with GMT offset of -8 hours.'); + $this->drupalGet("node/$node2->nid"); + $this->assertText('2007-08-01 00:00:00 -0700', 'Date should be three hours ahead, with GMT offset of -7 hours.'); + } +} + class PageTitleFiltering extends DrupalWebTestCase { protected $content_user; protected $saved_title; @@ -532,4 +573,3 @@ class PageTitleFiltering extends DrupalW $this->assertText(check_plain($edit['title']), 'Check to make sure tags in the node title are converted.'); } } - Index: modules/user/user.install =================================================================== RCS file: /cvs/drupal/drupal/modules/user/user.install,v retrieving revision 1.13 diff -u -p -r1.13 user.install --- modules/user/user.install 20 Sep 2008 20:22:25 -0000 1.13 +++ modules/user/user.install 3 Nov 2008 00:07:37 -0000 @@ -158,9 +158,9 @@ function user_schema() { ), 'timezone' => array( 'type' => 'varchar', - 'length' => 8, + 'length' => 32, 'not null' => FALSE, - 'description' => t("User's timezone."), + 'description' => t("User's time zone."), ), 'language' => array( 'type' => 'varchar', @@ -292,6 +292,34 @@ function user_update_7001() { } /** + * Convert user time zones from time zone offsets to time zone names. + */ +function user_update_7002() { + $ret = array(); + db_change_field($ret, 'users', 'timezone', 'timezone', array('type' => 'varchar', 'length' => 32, 'not null' => FALSE, 'description' => t("User's time zone."))); + // If the contributed Date module has created a users.timezone_name + // column, use this data to set each user's time zone. + if (db_column_exists('users', 'timezone_name')) { + $ret[] = update_sql("UPDATE {users} SET timezone = timezone_name"); + } + // If the contributed Event module has stored user time zone information + // use that information to update the user accounts. + elseif (db_column_exists('users', 'timezone_id')) { + $results = db_query("SELECT DISTINCT u.timezone_id, t.name FROM {users} u LEFT JOIN {event_timezones} t on u.timezone_id = t.timezone"); + foreach ($results as $row) { + $name = str_replace(' ', '_', $row->name); + $ret[] = update_sql("UPDATE {users} SET timezone = '$name' WHERE timezone_id = " . $row->timezone_id); + } + } + else { + $ret[] = update_sql("UPDATE {users} SET timezone = NULL"); + variable_set('empty_timezone_message', 1); + drupal_set_message(t('User time zones have been emptied and need to be set to the correct values. Use the new time zone options to choose whether to remind users at login to set the correct time zone.', array('!date-settings' => url('admin/settings/date-time'))), 'warning'); + } + return $ret; +} + +/** * @} End of "defgroup user-updates-6.x-to-7.x" * The next series of updates should start at 8000. */ Index: modules/user/user.js =================================================================== RCS file: /cvs/drupal/drupal/modules/user/user.js,v retrieving revision 1.8 diff -u -p -r1.8 user.js --- modules/user/user.js 29 Oct 2008 10:01:28 -0000 1.8 +++ modules/user/user.js 2 Nov 2008 23:32:57 -0000 @@ -160,14 +160,6 @@ Drupal.evaluatePasswordStrength = functi }; /** - * Set the client's system timezone as default values of form fields. - */ -Drupal.setDefaultTimezone = function() { - var offset = new Date().getTimezoneOffset() * -60; - $("#edit-date-default-timezone, #edit-user-register-timezone").val(offset); -}; - -/** * On the admin/user/settings page, conditionally show all of the * picture-related form elements depending on the current value of the * "Picture support" radio buttons. Index: modules/user/user.module =================================================================== RCS file: /cvs/drupal/drupal/modules/user/user.module,v retrieving revision 1.930 diff -u -p -r1.930 user.module --- modules/user/user.module 26 Oct 2008 18:06:39 -0000 1.930 +++ modules/user/user.module 2 Nov 2008 23:32:57 -0000 @@ -2403,25 +2403,6 @@ function user_register() { $form = array_merge($form, $extra); } - if (variable_get('configurable_timezones', 1)) { - // Override field ID, so we only change timezone on user registration, - // and never touch it on user edit pages. - $form['timezone'] = array( - '#type' => 'hidden', - '#default_value' => variable_get('date_default_timezone', NULL), - '#id' => 'edit-user-register-timezone', - ); - - // Add the JavaScript callback to automatically set the timezone. - drupal_add_js(' -// Global Killswitch -if (Drupal.jsEnabled) { - $(document).ready(function() { - Drupal.setDefaultTimezone(); - }); -}', 'inline'); - } - $form['submit'] = array('#type' => 'submit', '#value' => t('Create new account'), '#weight' => 30); $form['#validate'][] = 'user_register_validate'; Index: modules/user/user.test =================================================================== RCS file: /cvs/drupal/drupal/modules/user/user.test,v retrieving revision 1.17 diff -u -p -r1.17 user.test --- modules/user/user.test 10 Oct 2008 07:49:49 -0000 1.17 +++ modules/user/user.test 2 Nov 2008 23:32:57 -0000 @@ -23,9 +23,9 @@ class UserRegistrationTestCase extends D // Set user registration to "Visitors can create accounts and no administrator approval is required." variable_set('user_register', 1); - // Enable user configurable timezone, and set the default timezone to +1 hour (or +3600 seconds). + // Enable user-configurable time zones, and set the default time zone to Brussels time. variable_set('configurable_timezones', 1); - variable_set('date_default_timezone', 3600); + variable_set('date_default_timezone', 'Europe/Brussels'); $edit = array(); $edit['name'] = $name = $this->randomName(); @@ -45,7 +45,7 @@ class UserRegistrationTestCase extends D $this->assertEqual($user->signature, '', t('Correct signature field.')); $this->assertTrue(($user->created > REQUEST_TIME - 20 ), t('Correct creation time.')); $this->assertEqual($user->status, variable_get('user_register', 1) == 1 ? 1 : 0, t('Correct status field.')); - $this->assertEqual($user->timezone, variable_get('date_default_timezone', NULL), t('Correct timezone field.')); + $this->assertEqual($user->timezone, variable_get('date_default_timezone', NULL), t('Correct time zone field.')); $this->assertEqual($user->language, '', t('Correct language field.')); $this->assertEqual($user->picture, '', t('Correct picture field.')); $this->assertEqual($user->init, $mail, t('Correct init field.')); @@ -524,6 +524,61 @@ class UserAdminTestCase extends DrupalWe } } +class UserTimeZoneTestCase extends DrupalWebTestCase { + /** + * Implementation of getInfo(). + */ + function getInfo() { + return array( + 'name' => t('User time zone'), + 'description' => t('Set a user time zone and verify that dates are displayed in local time.'), + 'group' => t('User'), + ); + } + + function testUserTimeZone() { + // Setup date/time settings for Los Angeles time. + variable_set('date_default_timezone', 'America/Los_Angeles'); + variable_set('configurable_timezones', 1); + variable_set('date_format_medium', 'Y-m-d H:i T'); + + // Create a user account and login. + $web_user = $this->drupalCreateUser(); + $this->drupalLogin($web_user); + + // Create some nodes with different authored-on dates. + $date1 = '2007-03-09 21:00:00 -0800'; + $date2 = '2007-03-11 01:00:00 -0800'; + $date3 = '2007-03-20 21:00:00 -0700'; + $node1 = $this->drupalCreateNode(array('created' => strtotime($date1), 'type' => 'article')); + $node2 = $this->drupalCreateNode(array('created' => strtotime($date2), 'type' => 'article')); + $node3 = $this->drupalCreateNode(array('created' => strtotime($date3), 'type' => 'article')); + + // Confirm date format and time zone. + $this->drupalGet("node/$node1->nid"); + $this->assertText('2007-03-09 21:00 PST', 'Date should be PST.'); + $this->drupalGet("node/$node2->nid"); + $this->assertText('2007-03-11 01:00 PST', 'Date should be PST.'); + $this->drupalGet("node/$node3->nid"); + $this->assertText('2007-03-20 21:00 PDT', 'Date should be PDT.'); + + // Change user time zone to Santiago time. + $edit = array(); + $edit['mail'] = $web_user->mail; + $edit['timezone'] = 'America/Santiago'; + $this->drupalPost("user/$web_user->uid/edit", $edit, t('Save')); + $this->assertText(t('The changes have been saved.'), t('Time zone changed to Santiago time.')); + + // Confirm date format and time zone. + $this->drupalGet("node/$node1->nid"); + $this->assertText('2007-03-10 02:00 CLST', 'Date should be Chile summer time; five hours ahead of PST.'); + $this->drupalGet("node/$node2->nid"); + $this->assertText('2007-03-11 05:00 CLT', 'Date should be Chile time; four hours ahead of PST'); + $this->drupalGet("node/$node3->nid"); + $this->assertText('2007-03-21 00:00 CLT', 'Date should be Chile time; three hours ahead of PDT.'); + } +} + /** * Test user autocompletion. */