Modernized the "timezone hack", made the config option a dropdown, and moved all timezone-related code into a new TimeZoneConfig class
3 /* Reminder: always indent with 4 spaces (no tabs). */
4 // +---------------------------------------------------------------------------+
6 // +---------------------------------------------------------------------------+
7 // | timezoneconfig.class.php |
9 // | Helper class for time zone handling |
10 // +---------------------------------------------------------------------------+
11 // | Copyright (C) 2009 by the following authors: |
13 // | Authors: Dirk Haun - dirk AT haun-online DOT de |
14 // | based on earlier work by Oliver Spiesshofer, Yew Loong, and others |
15 // +---------------------------------------------------------------------------+
17 // | This program is free software; you can redistribute it and/or |
18 // | modify it under the terms of the GNU General Public License |
19 // | as published by the Free Software Foundation; either version 2 |
20 // | of the License, or (at your option) any later version. |
22 // | This program is distributed in the hope that it will be useful, |
23 // | but WITHOUT ANY WARRANTY; without even the implied warranty of |
24 // | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
25 // | GNU General Public License for more details. |
27 // | You should have received a copy of the GNU General Public License |
28 // | along with this program; if not, write to the Free Software Foundation, |
29 // | Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
31 // +---------------------------------------------------------------------------+
34 * Geeklog Time Zone Config class
36 * A collection of static (for now) methods dealing with time zone handling.
38 * For the original "Timezone Hack" discussion, see
39 * @link http://www.geeklog.net/forum/viewtopic.php?showtopic=21232
41 * @author Dirk Haun, dirk AT haun-online DOT de
44 class TimeZoneConfig {
47 * Set the system's timezone
49 * @param string $tz timezone to set; use $_CONF['timezone'] if empty
54 function setSystemTimeZone($tz = '')
58 if (empty($tz) && !empty($_CONF['timezone'])) {
59 $tz = $_CONF['timezone'];
63 if (function_exists('date_default_timezone_set')) {
64 if (! @date_default_timezone_set($tz)) {
65 date_default_timezone_set('UTC');
66 COM_errorLog("Timezone '$tz' not valid - using 'UTC' instead", 1);
68 } elseif (!ini_get('safe_mode') && function_exists('putenv')) {
69 // aka "Timezone Hack"
72 } elseif (function_exists('date_default_timezone_get')) {
73 // this is not ideal but will stop PHP 5.3.0ff from complaining ...
74 date_default_timezone_set(@date_default_timezone_get());
79 * Get the user's preferred timezone
81 * @return string name of the timezone
85 function getUserTimeZone()
87 global $_CONF, $_USER;
89 if (! empty($_USER['tzid'])) {
90 $timezone = $_USER['tzid'];
91 } elseif (! empty($_CONF['timezone'])) {
92 $timezone = $_CONF['timezone'];
94 require_once 'Date/TimeZone.php';
96 $tz_obj = Date_TimeZone::getDefault();
97 $timezone = $tz_obj->id;
104 * Provide a dropdown menu of the available timezones
106 * @return string HTML for the dropdown
110 function getTimeZoneDropDown($selected = '', $attributes = array())
112 $timezones = TimeZoneConfig::listAvailableTimeZones();
114 $selection = '<select';
115 foreach ($attributes as $name => $value) {
116 $selection .= sprintf(' %s="%s"', $name, $value);
118 $selection .= '>' . LB;
120 foreach ($timezones as $tzid => $tzdisplay) {
121 $selection .= '<option value="' . $tzid . '"';
122 if (!empty($selected) && ($selected == $tzid)) {
123 $selection .= ' selected="selected"';
125 $selection .= ">$tzdisplay</option>" . LB;
127 $selection .= '</select>';
133 * Provide a list of available timezones
135 * @return array array of (timezone-short-name, timezone-long-name) pairs
139 function listAvailableTimeZones()
141 $timezones = array();
143 // use only timezones that contain one of these
144 $useonly = array('Africa', 'America', 'Antarctica', 'Arctic', 'Asia',
145 'Atlantic', 'Australia', 'Europe', 'Indian', 'Pacific',
148 // check if we can use the DateTimeZone class
149 $useDateTimeZone = false;
150 if (class_exists('DateTimeZone') && class_exists('ReflectionClass')) {
151 $rc = new ReflectionClass('DateTimeZone');
152 if ($rc->hasMethod('listAbbreviations')) {
153 $useDateTimeZone = true;
157 if ($useDateTimeZone) {
159 $T = DateTimeZone::listAbbreviations();
160 foreach ($T as $tzid => $entries) {
161 $shortname = strtoupper($tzid);
162 foreach ($entries as $data) {
163 $tzcheck = explode('/', $data['timezone_id']);
164 if (! in_array($tzcheck[0], $useonly)) {
168 $hours = $data['offset'] / 3600;
169 $hours = ((int) ($hours * 100) / 100);
174 $tzcode = str_replace('_', ' ', $data['timezone_id']);
175 $tzcode = htmlspecialchars($tzcode);
176 $formattedTimezone = "$hours, $shortname ($tzcode)";
177 $timezones[$data['timezone_id']] = $formattedTimezone;
181 } else { // DateTimeZone not available - use PEAR Date class
183 require_once 'Date/TimeZone.php';
185 $T = $GLOBALS['_DATE_TIMEZONE_DATA'];
187 foreach ($T as $tzid => $tDetails) {
188 $tzcheck = explode('/', $tzid);
189 if (! in_array($tzcheck[0], $useonly)) {
192 if (!empty($tzcheck[1]) &&
193 (strpos($tzcheck[1], 'Riyadh') === 0)) {
194 // these time zones are based on solar time and not widely
199 $tzcode = str_replace('_', ' ', $tzid);
200 $tzcode = htmlspecialchars($tzcode);
201 $hours = $tDetails['offset'] / (3600 * 1000);
202 $hours = ((int) ($hours * 100) / 100);
207 $formattedTimezone = "$hours, {$tDetails['shortname']} ($tzcode)";
208 $timezones[$tzid] = $formattedTimezone;
213 uasort($timezones, 'TimeZoneConfig::_sort_by_timezone');
219 * Helper method: Sort timezone entries
221 * @param string $tz1 first timezone
222 * @param string $tz2 second timezone
223 * @return int 0: equal, <0: first<second, >0: first>second
228 function _sort_by_timezone($tz1, $tz2)
230 $p1 = explode(',', $tz1);
231 $p2 = explode(',', $tz2);
237 return ($o1 < $o2 ? -1 : 1);
240 // drop offset, pop timezone name, then add it to the end again
242 $tz1 = trim(implode(',', $p1));
243 $p1 = explode(' ', $tz1);
244 $x1 = array_shift($p1);
246 $tz1 = implode(' ', $p1);
249 $tz2 = trim(implode(',', $p2));
250 $p2 = explode(' ', $tz2);
251 $x2 = array_shift($p2);
253 $tz2 = implode(' ', $p2);
255 return strcmp($tz1, $tz2);