From 5879c09ca046c483d4102f1dd21babfac1cd8057 Mon Sep 17 00:00:00 2001 From: thomascube Date: Wed, 4 Jan 2012 12:47:50 +0000 Subject: Use proper timezones from PHP's internal timezonedb (#1485592) --- program/include/main.inc | 46 ++++++++++------------- program/include/rcube_config.php | 30 +++++++++++---- program/steps/settings/func.inc | 71 ++++++++++------------------------- program/steps/settings/save_prefs.inc | 3 +- 4 files changed, 62 insertions(+), 88 deletions(-) (limited to 'program') diff --git a/program/include/main.inc b/program/include/main.inc index ac804bd0a..ad41a13e7 100644 --- a/program/include/main.inc +++ b/program/include/main.inc @@ -1062,22 +1062,16 @@ function format_date($date, $format=NULL, $convert=true) if (empty($ts)) return ''; - if ($convert) { - // get user's timezone offset - $tz = $RCMAIL->config->get_timezone(); + $date = new DateTime; + $date->setTimestamp($ts); - // convert time to user's timezone - $timestamp = $ts - date('Z', $ts) + ($tz * 3600); + // convert to the right timezone + $stz = date_default_timezone_get(); + $tz = new DateTimeZone($convert ? $RCMAIL->config->get('timezone') : 'GMT'); + date_default_timezone_set($tz->getName()); + $date->setTimezone($tz); - // get current timestamp in user's timezone - $now = time(); // local time - $now -= (int)date('Z'); // make GMT time - $now += ($tz * 3600); // user's time - } - else { - $now = time(); - $timestamp = $ts; - } + $timestamp = $date->getTimestamp(); // define date format depending on current time if (!$format) { @@ -1098,6 +1092,7 @@ function format_date($date, $format=NULL, $convert=true) // strftime() format if (preg_match('/%[a-z]+/i', $format)) { $format = strftime($format, $timestamp); + date_default_timezone_set($stz); return $today ? (rcube_label('today') . ' ' . $format) : $format; } @@ -1113,20 +1108,20 @@ function format_date($date, $format=NULL, $convert=true) $out .= $format[$i]; // weekday (short) else if ($format[$i]=='D') - $out .= rcube_label(strtolower(date('D', $timestamp))); + $out .= rcube_label(strtolower($date->format('D'))); // weekday long else if ($format[$i]=='l') - $out .= rcube_label(strtolower(date('l', $timestamp))); + $out .= rcube_label(strtolower($date->format('l'))); // month name (short) else if ($format[$i]=='M') - $out .= rcube_label(strtolower(date('M', $timestamp))); + $out .= rcube_label(strtolower($date->format('M'))); // month name (long) else if ($format[$i]=='F') - $out .= rcube_label('long'.strtolower(date('M', $timestamp))); + $out .= rcube_label('long'.strtolower($date->format('M'))); else if ($format[$i]=='x') $out .= strftime('%x %X', $timestamp); else - $out .= date($format[$i], $timestamp); + $out .= $date->format($format[$i]); } if ($today) { @@ -1140,6 +1135,7 @@ function format_date($date, $format=NULL, $convert=true) } } + date_default_timezone_set($stz); return $out; } @@ -1878,17 +1874,13 @@ function rcmail_gen_message_id() // Returns RFC2822 formatted current date in user's timezone function rcmail_user_date() { - global $RCMAIL, $CONFIG; + global $RCMAIL; // get user's timezone - $tz = $RCMAIL->config->get_timezone(); - - $date = time() + $tz * 60 * 60; - $date = gmdate('r', $date); - $tz = sprintf('%+05d', intval($tz) * 100 + ($tz - intval($tz)) * 60); - $date = preg_replace('/[+-][0-9]{4}$/', $tz, $date); + $tz = new DateTimeZone($RCMAIL->config->get('timezone')); - return $date; + $date = new DateTime('now', $tz); + return $date->format('r'); } diff --git a/program/include/rcube_config.php b/program/include/rcube_config.php index f80f92c91..18a90a969 100644 --- a/program/include/rcube_config.php +++ b/program/include/rcube_config.php @@ -93,13 +93,15 @@ class rcube_config // set timezone auto settings values if ($this->prop['timezone'] == 'auto') { - $this->prop['dst_active'] = intval(date('I')); - $this->prop['_timezone_value'] = date('Z') / 3600 - $this->prop['dst_active']; + $this->prop['_timezone_value'] = $this->client_timezone(); } - else if ($this->prop['dst_active'] === null) { - $this->prop['dst_active'] = intval(date('I')); + else if (is_numeric($this->prop['timezone'])) { + $this->prop['timezone'] = timezone_name_from_abbr("", $this->prop['timezone'] * 3600, 0); } + // remove deprecated properties + unset($this->prop['dst_active']); + // export config data $GLOBALS['CONFIG'] = &$this->prop; } @@ -222,8 +224,7 @@ class rcube_config // override timezone settings with client values if ($this->prop['timezone'] == 'auto') { - $this->prop['_timezone_value'] = isset($_SESSION['timezone']) ? $_SESSION['timezone'] : $this->prop['_timezone_value']; - $this->prop['dst_active'] = $this->userprefs['dst_active'] = isset($_SESSION['dst_active']) ? $_SESSION['dst_active'] : $this->prop['dst_active']; + $this->prop['_timezone_value'] = isset($_SESSION['timezone']) ? $this->client_timezone() : $this->prop['_timezone_value']; } else if (isset($this->prop['_timezone_value'])) unset($this->prop['_timezone_value']); @@ -244,10 +245,16 @@ class rcube_config * Special getter for user's timezone offset including DST * * @return float Timezone offset (in hours) + * @deprecated */ public function get_timezone() { - return floatval($this->get('timezone')) + intval($this->get('dst_active')); + if ($this->get('timezone')) { + $tz = new DateTimeZone($this->get('timezone')); + return $tz->getOffset(new DateTime('now')) / 3600; + } + + return 0; } /** @@ -349,4 +356,13 @@ class rcube_config return empty($this->errors) ? false : join("\n", $this->errors); } + + /** + * Internal getter for client's (browser) timezone identifier + */ + private function client_timezone() + { + return isset($_SESSION['timezone']) ? timezone_name_from_abbr("", $_SESSION['timezone'] * 3600, 0) : date_default_timezone_get(); + } + } diff --git a/program/steps/settings/func.inc b/program/steps/settings/func.inc index 2050b9331..44d3610f9 100644 --- a/program/steps/settings/func.inc +++ b/program/steps/settings/func.inc @@ -177,48 +177,26 @@ function rcmail_user_prefs($current=null) // timezone selection if (!isset($no_override['timezone'])) { $field_id = 'rcmfd_timezone'; - $select_timezone = new html_select(array('name' => '_timezone', 'id' => $field_id, - 'onchange' => "$('#rcmfd_dst').attr('disabled', this.selectedIndex==0)")); + $select_timezone = new html_select(array('name' => '_timezone', 'id' => $field_id)); $select_timezone->add(rcube_label('autodetect'), 'auto'); - $select_timezone->add('(GMT -11:00) Midway Island, Samoa', '-11'); - $select_timezone->add('(GMT -10:00) Hawaii', '-10'); - $select_timezone->add('(GMT -9:30) Marquesas Islands', '-9.5'); - $select_timezone->add('(GMT -9:00) Alaska', '-9'); - $select_timezone->add('(GMT -8:00) Pacific Time (US/Canada)', '-8'); - $select_timezone->add('(GMT -7:00) Mountain Time (US/Canada)', '-7'); - $select_timezone->add('(GMT -6:00) Central Time (US/Canada), Mexico City', '-6'); - $select_timezone->add('(GMT -5:00) Eastern Time (US/Canada), Bogota, Lima', '-5'); - $select_timezone->add('(GMT -4:30) Caracas', '-4.5'); - $select_timezone->add('(GMT -4:00) Atlantic Time (Canada), La Paz', '-4'); - $select_timezone->add('(GMT -3:30) Nfld Time (Canada), Nfld, S. Labador', '-3.5'); - $select_timezone->add('(GMT -3:00) Brazil, Buenos Aires, Georgetown', '-3'); - $select_timezone->add('(GMT -2:00) Mid-Atlantic', '-2'); - $select_timezone->add('(GMT -1:00) Azores, Cape Verde Islands', '-1'); - $select_timezone->add('(GMT) Western Europe, London, Lisbon, Casablanca', '0'); - $select_timezone->add('(GMT +1:00) Central European Time', '1'); - $select_timezone->add('(GMT +2:00) EET: Tallinn, Helsinki, Kaliningrad, South Africa', '2'); - $select_timezone->add('(GMT +3:00) Baghdad, Kuwait, Riyadh, Moscow, Nairobi', '3'); - $select_timezone->add('(GMT +3:30) Tehran', '3.5'); - $select_timezone->add('(GMT +4:00) Abu Dhabi, Muscat, Baku, Tbilisi', '4'); - $select_timezone->add('(GMT +4:30) Kabul', '4.5'); - $select_timezone->add('(GMT +5:00) Ekaterinburg, Islamabad, Karachi', '5'); - $select_timezone->add('(GMT +5:30) Chennai, Kolkata, Mumbai, New Delhi', '5.5'); - $select_timezone->add('(GMT +5:45) Kathmandu', '5.75'); - $select_timezone->add('(GMT +6:00) Almaty, Dhaka, Colombo', '6'); - $select_timezone->add('(GMT +6:30) Cocos Islands, Myanmar', '6.5'); - $select_timezone->add('(GMT +7:00) Bangkok, Hanoi, Jakarta', '7'); - $select_timezone->add('(GMT +8:00) Beijing, Perth, Singapore, Taipei', '8'); - $select_timezone->add('(GMT +8:45) Caiguna, Eucla, Border Village', '8.75'); - $select_timezone->add('(GMT +9:00) Tokyo, Seoul, Yakutsk', '9'); - $select_timezone->add('(GMT +9:30) Adelaide, Darwin', '9.5'); - $select_timezone->add('(GMT +10:00) EAST/AEST: Sydney, Guam, Vladivostok', '10'); - $select_timezone->add('(GMT +10:30) New South Wales', '10.5'); - $select_timezone->add('(GMT +11:00) Magadan, Solomon Islands', '11'); - $select_timezone->add('(GMT +11:30) Norfolk Island', '11.5'); - $select_timezone->add('(GMT +12:00) Auckland, Wellington, Kamchatka', '12'); - $select_timezone->add('(GMT +12:45) Chatham Islands', '12.75'); - $select_timezone->add('(GMT +13:00) Tonga, Pheonix Islands', '13'); - $select_timezone->add('(GMT +14:00) Kiribati', '14'); + + $now = new DateTime(); + foreach (DateTimeZone::listIdentifiers() as $i => $tzs) { + $tz = new DateTimeZone($tzs); + $date = new DateTime('2012-12-21', $tz); + $offset = $date->format('Z') + 45000; + $sortkey = sprintf('%06d.%s', $offset, $tzs); + $zones[$sortkey] = array($tzs, $date->format('P')); + } + + ksort($zones); + foreach ($zones as $zone) { + list($tzs, $offset) = $zone; + $select_timezone->add('(GMT ' . $offset . ') ' . strtr($tzs, '_', ' '), $tzs); + } + + if (is_numeric($config['timezone'])) + timezone_name_from_abbr("", $config['timezone'] * 3600, 0); $blocks['main']['options']['timezone'] = array( 'title' => html::label($field_id, Q(rcube_label('timezone'))), @@ -226,17 +204,6 @@ function rcmail_user_prefs($current=null) ); } - // daylight savings - if (!isset($no_override['dst_active'])) { - $field_id = 'rcmfd_dst'; - $input_dst = new html_checkbox(array('name' => '_dst_active', 'id' => $field_id, 'value' => 1, 'disabled' => ($config['timezone'] === 'auto'))); - - $blocks['main']['options']['dstactive'] = array( - 'title' => html::label($field_id, Q(rcube_label('dstactive'))), - 'content' => $input_dst->show($config['dst_active']), - ); - } - // date/time formatting if (!isset($no_override['time_format'])) { $reftime = mktime(7,30,0); diff --git a/program/steps/settings/save_prefs.inc b/program/steps/settings/save_prefs.inc index 2e89ce1c0..36d401ed4 100644 --- a/program/steps/settings/save_prefs.inc +++ b/program/steps/settings/save_prefs.inc @@ -29,8 +29,7 @@ switch ($CURR_SECTION) case 'general': $a_user_prefs = array( 'language' => isset($_POST['_language']) ? get_input_value('_language', RCUBE_INPUT_POST) : $CONFIG['language'], - 'timezone' => isset($_POST['_timezone']) ? (is_numeric($_POST['_timezone']) ? floatval($_POST['_timezone']) : get_input_value('_timezone', RCUBE_INPUT_POST)) : $CONFIG['timezone'], - 'dst_active' => isset($_POST['_dst_active']) ? TRUE : FALSE, + 'timezone' => isset($_POST['_timezone']) ? get_input_value('_timezone', RCUBE_INPUT_POST) : $CONFIG['timezone'], 'date_format' => isset($_POST['_date_format']) ? get_input_value('_date_format', RCUBE_INPUT_POST) : $CONFIG['date_format'], 'time_format' => isset($_POST['_time_format']) ? get_input_value('_time_format', RCUBE_INPUT_POST) : ($CONFIG['time_format'] ? $CONFIG['time_format'] : 'H:i'), 'prettydate' => isset($_POST['_pretty_date']) ? TRUE : FALSE, -- cgit v1.2.3