summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.txt10
-rw-r--r--includes/common.inc37
-rw-r--r--install.php8
-rw-r--r--modules/system/system.admin.inc48
-rw-r--r--modules/system/system.install42
-rw-r--r--modules/system/system.js3
-rw-r--r--modules/system/system.module125
-rw-r--r--modules/system/system.test45
-rw-r--r--modules/user/user.install72
-rw-r--r--modules/user/user.js8
-rw-r--r--modules/user/user.module19
-rw-r--r--modules/user/user.test66
12 files changed, 396 insertions, 87 deletions
diff --git a/CHANGELOG.txt b/CHANGELOG.txt
index 384f01cd1..0470b2baf 100644
--- a/CHANGELOG.txt
+++ b/CHANGELOG.txt
@@ -37,6 +37,16 @@ Drupal 7.0, xxxx-xx-xx (development version)
* 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
+ fallback to the system time zone and 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:
diff --git a/includes/common.inc b/includes/common.inc
index 7ac9bad5b..e944ca300 100644
--- a/includes/common.inc
+++ b/includes/common.inc
@@ -1340,7 +1340,7 @@ function format_interval($timestamp, $granularity = 2, $langcode = NULL) {
* 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.
@@ -1348,17 +1348,21 @@ function format_interval($timestamp, $granularity = 2, $langcode = NULL) {
* 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':
@@ -1377,28 +1381,27 @@ function format_date($timestamp, $type = 'medium', $format = '', $timezone = NUL
$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];
diff --git a/install.php b/install.php
index a510df20c..9b91d56d5 100644
--- a/install.php
+++ b/install.php
@@ -726,6 +726,8 @@ function install_tasks($profile, $task) {
// Add JavaScript validation.
_user_password_dynamic_validation();
drupal_add_js(drupal_get_path('module', 'system') . '/system.js');
+ // Add JavaScript time zone detection.
+ drupal_add_js('misc/timezone.js');
// We add these strings as settings because JavaScript translation does not
// work on install time.
drupal_add_js(array('copyFieldValue' => array('edit-site-mail' => array('edit-account-mail')), 'cleanURL' => array('success' => st('Your server has been successfully tested to support this feature.'), 'failure' => st('Your system configuration does not currently support this feature. The <a href="http://drupal.org/node/15365">handbook page on Clean URLs</a> has additional troubleshooting information.'), 'testing' => st('Testing clean URLs...'))), 'setting');
@@ -734,7 +736,6 @@ function install_tasks($profile, $task) {
if (Drupal.jsEnabled) {
$(document).ready(function() {
Drupal.cleanURLsInstallCheck();
- Drupal.setDefaultTimezone();
});
}', 'inline');
// Build menu to allow clean URL check.
@@ -1081,10 +1082,11 @@ function install_configure_form(&$form_state, $url) {
$form['server_settings']['date_default_timezone'] = array(
'#type' => 'select',
'#title' => st('Default time zone'),
- '#default_value' => 0,
- '#options' => _system_zonelist(),
+ '#default_value' => date_default_timezone_get(),
+ '#options' => system_time_zones(),
'#description' => st('By default, dates in this site will be displayed in the chosen time zone.'),
'#weight' => 5,
+ '#attributes' => array('class' => 'timezone-detect'),
);
$form['server_settings']['clean_url'] = array(
diff --git a/modules/system/system.admin.inc b/modules/system/system.admin.inc
index fe94ba191..970c0488a 100644
--- a/modules/system/system.admin.inc
+++ b/modules/system/system.admin.inc
@@ -1532,7 +1532,7 @@ function system_date_time_settings() {
drupal_add_js(array('dateTime' => array('lookup' => url('admin/settings/date-time/lookup'))), 'setting');
// Date settings:
- $zones = _system_zonelist();
+ $zones = system_time_zones();
// Date settings: possible date formats
$date_short = array('Y-m-d H:i', 'm/d/Y - H:i', 'd/m/Y - H:i', 'Y/m/d - H:i',
@@ -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,42 @@ function system_date_time_settings() {
'#description' => t('The first day of the week for calendar views.')
);
+ $form['timezone'] = array(
+ '#type' => 'fieldset',
+ '#title' => t('User time zones'),
+ );
+
+ $form['timezone']['configurable_timezones'] = array(
+ '#type' => 'radios',
+ '#title' => t('User-configurable time zones'),
+ '#default_value' => variable_get('configurable_timezones', 1),
+ '#options' => array(0 => t('Disabled'), 1 => 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', DRUPAL_USER_TIMEZONE_DEFAULT),
+ '#options' => array(
+ DRUPAL_USER_TIMEZONE_DEFAULT => t('New users will be set to the default time zone at registration.'),
+ DRUPAL_USER_TIMEZONE_EMPTY => t('New users will get an empty time zone at registration.'),
+ DRUPAL_USER_TIMEZONE_SELECT => 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(
+ 0 => t('Ignore empty user time zones.'),
+ 1 => 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'),
diff --git a/modules/system/system.install b/modules/system/system.install
index 296e58be6..5d526c1dc 100644
--- a/modules/system/system.install
+++ b/modules/system/system.install
@@ -3097,7 +3097,47 @@ function system_update_7012() {
}
/**
+ * Convert default time zone offset to default time zone name.
+ */
+function system_update_7013() {
+ $ret = array();
+ $timezone = NULL;
+ $timezones = system_time_zones();
+ // If the contributed Date module set a default time zone name, use this
+ // setting as the default time zone.
+ if (($timezone_name = variable_get('date_default_timezone_name', NULL)) && isset($timezones[$timezone_name])) {
+ $timezone = $timezone_name;
+ }
+ // If the contributed Event module has set a default site time zone, look up
+ // the time zone name and use it as the default time zone.
+ if (!$timezone && ($timezone_id = variable_get('date_default_timezone_id', 0))) {
+ try {
+ $timezone_name = db_result(db_query('SELECT name FROM {event_timezones} WHERE timezone = :timezone_id', array(':timezone_id' => $timezone_id)));
+ if (($timezone_name = str_replace(' ', '_', $timezone_name)) && isset($timezones[$timezone_name])) {
+ $timezone = $timezone_name;
+ }
+ }
+ catch (PDOException $e) {
+ // Ignore error if event_timezones table does not exist or unexpected
+ // schema found.
+ }
+ }
+ // 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.
+ if (!$timezone && ($offset = variable_get('date_default_timezone', 0)) && ($timezone_name = timezone_name_from_abbr('', intval($offset), date('I'))) && isset($timezones[$timezone_name])) {
+ $timezone = $timezone_name;
+ }
+ // Otherwise, the default time zone offset was zero, which is UTC.
+ if (!$timezone) {
+ $timezone = 'UTC';
+ }
+ variable_set('date_default_timezone', $timezone);
+ drupal_set_message('The default time zone has been set to <em>' . check_plain($timezone) . '</em>. Please check the ' . l('date and time configuration page', 'admin/settings/date-time') . ' to configure it correctly.', 'warning');
+ return $ret;
+}
+
+/**
* @} End of "defgroup updates-6.x-to-7.x"
* The next series of updates should start at 8000.
*/
-
diff --git a/modules/system/system.js b/modules/system/system.js
index 3b477739e..8df6d5dd3 100644
--- a/modules/system/system.js
+++ b/modules/system/system.js
@@ -48,7 +48,10 @@ Drupal.cleanURLsInstallCheck = function() {
var url = location.protocol +"//"+ location.host + Drupal.settings.basePath +"admin/settings/clean-urls/check";
$("#clean-url .description").append('<span><div id="testing">'+ Drupal.settings.cleanURL.testing +"</div></span>");
$("#clean-url.install").css("display", "block");
+ // Submit a synchronous request to avoid database errors associated with
+ // concurrent requests during install.
$.ajax({
+ async: false,
url: url,
dataType: 'json',
success: function () {
diff --git a/modules/system/system.module b/modules/system/system.module
index 9be9edbfd..b010e8d55 100644
--- a/modules/system/system.module
+++ b/modules/system/system.module
@@ -42,6 +42,21 @@ define('DRUPAL_MINIMUM_PGSQL', '8.1');
define('DRUPAL_MAXIMUM_TEMP_FILE_AGE', 21600);
/**
+ * New users will be set to the default time zone at registration.
+ */
+define('DRUPAL_USER_TIMEZONE_DEFAULT', 0);
+
+/**
+ * New users will get an empty time zone at registration.
+ */
+define('DRUPAL_USER_TIMEZONE_EMPTY', 1);
+
+/**
+ * New users will select their own timezone at registration.
+ */
+define('DRUPAL_USER_TIMEZONE_SELECT', 2);
+
+/**
* Implementation of hook_help().
*/
function system_help($path, $arg) {
@@ -356,6 +371,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'),
@@ -591,7 +612,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'),
@@ -736,29 +757,68 @@ function system_preprocess_page(&$variables) {
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', DRUPAL_USER_TIMEZONE_DEFAULT) == DRUPAL_USER_TIMEZONE_SELECT) {
+ system_user_timezone($edit, $form);
+ }
+ else {
$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', DRUPAL_USER_TIMEZONE_DEFAULT) ? '' : variable_get('date_default_timezone', ''),
);
}
-
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 <a href="@user-edit">account time zone setting</a>.', 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_time_zones(($edit['uid'] != $user->uid)),
+ '#description' => t('Select the desired local time and time zone. 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.');
+ $form['timezone']['timezone']['#attributes'] = array('class' => 'timezone-detect');
+ drupal_add_js('misc/timezone.js');
+ }
+}
+
+/**
* Implementation of hook_block().
*
* Generate a block with a promotional link to Drupal.org.
@@ -2059,15 +2119,23 @@ function system_block_ip_action() {
/**
* Generate an array of time zones and their local time&date.
- */
-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);
+ *
+ * @param $blank
+ * If evaluates true, prepend an empty time zone option to the array.
+ */
+function system_time_zones($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)));
+ }
}
+ // Sort the translated time zones alphabetically.
+ asort($zones);
return $zones;
}
@@ -2098,6 +2166,17 @@ 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);
+ drupal_json($timezone);
+}
+
+/**
* Format the Powered by Drupal text.
*
* @ingroup themeable
diff --git a/modules/system/system.test b/modules/system/system.test
index 8db303a06..756b6c196 100644
--- a/modules/system/system.test
+++ b/modules/system/system.test
@@ -469,6 +469,50 @@ class PageNotFoundTestCase extends DrupalWebTestCase {
}
}
+/**
+ * Tests generic date and time handling capabilities of Drupal.
+ */
+class DateTimeFunctionalTest extends DrupalWebTestCase {
+ 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'),
+ );
+ }
+
+ /**
+ * Test time zones and DST handling.
+ */
+ function testTimeZoneHandling() {
+ // 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', t('Date should be identical, with GMT offset of -10 hours.'));
+ $this->drupalGet("node/$node2->nid");
+ $this->assertText('2007-07-31 21:00:00 -1000', t('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', t('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', t('Date should be three hours ahead, with GMT offset of -7 hours.'));
+ }
+}
+
class PageTitleFiltering extends DrupalWebTestCase {
protected $content_user;
protected $saved_title;
@@ -532,4 +576,3 @@ class PageTitleFiltering extends DrupalWebTestCase {
$this->assertText(check_plain($edit['title']), 'Check to make sure tags in the node title are converted.');
}
}
-
diff --git a/modules/user/user.install b/modules/user/user.install
index 0220e8589..0583d3cd1 100644
--- a/modules/user/user.install
+++ b/modules/user/user.install
@@ -158,9 +158,9 @@ function user_schema() {
),
'timezone' => array(
'type' => 'varchar',
- 'length' => 8,
+ 'length' => 32,
'not null' => FALSE,
- 'description' => "User's timezone.",
+ 'description' => "User's time zone.",
),
'language' => array(
'type' => 'varchar',
@@ -292,6 +292,74 @@ function user_update_7001() {
}
/**
+ * Convert user time zones from time zone offsets to time zone names.
+ */
+function user_update_7002(&$sandbox) {
+ $ret = array('#finished' => 0);
+
+ // Multi-part update.
+ if (!isset($sandbox['user_from'])) {
+ db_change_field($ret, 'users', 'timezone', 'timezone', array('type' => 'varchar', 'length' => 32, 'not null' => FALSE));
+ $sandbox['user_from'] = 0;
+ $sandbox['user_count'] = db_result(db_query("SELECT COUNT(uid) FROM {users}"));
+ $sandbox['user_not_migrated'] = 0;
+ }
+ else {
+ $timezones = system_time_zones();
+ // Update this many per page load.
+ $count = 10000;
+ $contributed_date_module = db_column_exists('users', 'timezone_name');
+ $contributed_event_module = db_column_exists('users', 'timezone_id');
+
+ $results = db_query_range("SELECT uid FROM {users} ORDER BY uid", array(), $sandbox['user_from'], $count);
+ foreach ($results as $account) {
+ $timezone = NULL;
+ // If the contributed Date module has created a users.timezone_name
+ // column, use this data to set each user's time zone.
+ if ($contributed_date_module) {
+ $date_timezone = db_query("SELECT timezone_name FROM {users} WHERE uid = :uid", array(':uid' => $account->uid))->fetchField();
+ if (isset($timezones[$date_timezone])) {
+ $timezone = $date_timezone;
+ }
+ }
+ // If the contributed Event module has stored user time zone information
+ // use that information to update the user accounts.
+ if (!$timezone && $contributed_event_module) {
+ try {
+ $event_timezone = db_query("SELECT t.name FROM {users} u LEFT JOIN {event_timezones} t ON u.timezone_id = t.timezone WHERE u.uid = :uid", array(':uid' => $account->uid))->fetchField();
+ $event_timezone = str_replace(' ', '_', $event_timezone);
+ if (isset($timezones[$event_timezone])) {
+ $timezone = $event_timezone;
+ }
+ }
+ catch (PDOException $e) {
+ // Ignore error if event_timezones table does not exist or unexpected
+ // schema found.
+ }
+ }
+ if ($timezone) {
+ db_query("UPDATE {users} SET timezone = :timezone WHERE uid = :uid", array(':timezone' => $timezone, ':uid' => $account->uid));
+ }
+ else {
+ $sandbox['user_not_migrated']++;
+ db_query("UPDATE {users} SET timezone = NULL WHERE uid = :uid", array(':uid' => $account->uid));
+ }
+ $sandbox['user_from']++;
+ }
+
+ $ret['#finished'] = $sandbox['user_from'] / $sandbox['user_count'];
+ if ($sandbox['user_from'] == $sandbox['user_count']) {
+ $ret[] = array('success' => TRUE, 'query' => "Migrate user time zones.");
+ if ($sandbox['user_not_migrated'] > 0) {
+ variable_set('empty_timezone_message', 1);
+ drupal_set_message('Some user time zones have been emptied and need to be set to the correct values. Use the new ' . l('time zone options', 'admin/settings/date-time') . ' to choose whether to remind users at login to set the correct time zone.', 'warning');
+ }
+ }
+ }
+ return $ret;
+}
+
+/**
* @} End of "defgroup user-updates-6.x-to-7.x"
* The next series of updates should start at 8000.
*/
diff --git a/modules/user/user.js b/modules/user/user.js
index 173a4879b..926a92137 100644
--- a/modules/user/user.js
+++ b/modules/user/user.js
@@ -160,14 +160,6 @@ Drupal.evaluatePasswordStrength = function (password) {
};
/**
- * 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.
diff --git a/modules/user/user.module b/modules/user/user.module
index 130c0f07e..6e8b83a80 100644
--- a/modules/user/user.module
+++ b/modules/user/user.module
@@ -2390,25 +2390,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';
diff --git a/modules/user/user.test b/modules/user/user.test
index 91e1df32e..bfe12858f 100644
--- a/modules/user/user.test
+++ b/modules/user/user.test
@@ -23,9 +23,9 @@ class UserRegistrationTestCase extends DrupalWebTestCase {
// 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 DrupalWebTestCase {
$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.'));
@@ -525,6 +525,66 @@ class UserAdminTestCase extends DrupalWebTestCase {
}
/**
+ * Tests for user-configurable time zones.
+ */
+class UserTimeZoneFunctionalTest extends DrupalWebTestCase {
+ function getInfo() {
+ return array(
+ 'name' => t('User time zones'),
+ 'description' => t('Set a user time zone and verify that dates are displayed in local time.'),
+ 'group' => t('User'),
+ );
+ }
+
+ /**
+ * Tests the display of dates and time when user-configurable time zones are set.
+ */
+ 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.
+ // Two dates in PST (winter time):
+ $date1 = '2007-03-09 21:00:00 -0800';
+ $date2 = '2007-03-11 01:00:00 -0800';
+ // One date in PDT (summer time):
+ $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', t('Date should be PST.'));
+ $this->drupalGet("node/$node2->nid");
+ $this->assertText('2007-03-11 01:00 PST', t('Date should be PST.'));
+ $this->drupalGet("node/$node3->nid");
+ $this->assertText('2007-03-20 21:00 PDT', t('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', t('Date should be Chile summer time; five hours ahead of PST.'));
+ $this->drupalGet("node/$node2->nid");
+ $this->assertText('2007-03-11 05:00 CLT', t('Date should be Chile time; four hours ahead of PST'));
+ $this->drupalGet("node/$node3->nid");
+ $this->assertText('2007-03-21 00:00 CLT', t('Date should be Chile time; three hours ahead of PDT.'));
+ }
+}
+
+/**
* Test user autocompletion.
*/
class UserAutocompleteTestCase extends DrupalWebTestCase {