system/classes/timezoneconfig.class.php
branchHEAD
changeset 7428 df55886043f2
child 7429 01f95a3e4545
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/system/classes/timezoneconfig.class.php	Sun Sep 20 11:00:03 2009 +0200
     1.3 @@ -0,0 +1,260 @@
     1.4 +<?php
     1.5 +
     1.6 +/* Reminder: always indent with 4 spaces (no tabs). */
     1.7 +// +---------------------------------------------------------------------------+
     1.8 +// | Geeklog 1.6                                                               |
     1.9 +// +---------------------------------------------------------------------------+
    1.10 +// | timezoneconfig.class.php                                                  |
    1.11 +// |                                                                           |
    1.12 +// | Helper class for time zone handling                                       |
    1.13 +// +---------------------------------------------------------------------------+
    1.14 +// | Copyright (C) 2009 by the following authors:                              |
    1.15 +// |                                                                           |
    1.16 +// | Authors: Dirk Haun             - dirk AT haun-online DOT de               |
    1.17 +// | based on earlier work by Oliver Spiesshofer, Yew Loong, and others        |
    1.18 +// +---------------------------------------------------------------------------+
    1.19 +// |                                                                           |
    1.20 +// | This program is free software; you can redistribute it and/or             |
    1.21 +// | modify it under the terms of the GNU General Public License               |
    1.22 +// | as published by the Free Software Foundation; either version 2            |
    1.23 +// | of the License, or (at your option) any later version.                    |
    1.24 +// |                                                                           |
    1.25 +// | This program is distributed in the hope that it will be useful,           |
    1.26 +// | but WITHOUT ANY WARRANTY; without even the implied warranty of            |
    1.27 +// | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             |
    1.28 +// | GNU General Public License for more details.                              |
    1.29 +// |                                                                           |
    1.30 +// | You should have received a copy of the GNU General Public License         |
    1.31 +// | along with this program; if not, write to the Free Software Foundation,   |
    1.32 +// | Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.           |
    1.33 +// |                                                                           |
    1.34 +// +---------------------------------------------------------------------------+
    1.35 +
    1.36 +/**
    1.37 +* Geeklog Time Zone Config class
    1.38 +*
    1.39 +* A collection of static (for now) methods dealing with time zone handling.
    1.40 +*
    1.41 +* For the original "Timezone Hack" discussion, see
    1.42 +* @link http://www.geeklog.net/forum/viewtopic.php?showtopic=21232
    1.43 +* 
    1.44 +* @author Dirk Haun, dirk AT haun-online DOT de
    1.45 +* 
    1.46 +*/
    1.47 +class TimeZoneConfig {
    1.48 +
    1.49 +    /**
    1.50 +    * Set the system's timezone
    1.51 +    *
    1.52 +    * @param    string  $tz     timezone to set; use $_CONF['timezone'] if empty
    1.53 +    * @return   void
    1.54 +    * @static
    1.55 +    *
    1.56 +    */
    1.57 +    function setSystemTimeZone($tz = '')
    1.58 +    {
    1.59 +        global $_CONF;
    1.60 +
    1.61 +        if (empty($tz) && !empty($_CONF['timezone'])) {
    1.62 +            $tz = $_CONF['timezone'];
    1.63 +        }
    1.64 +
    1.65 +        if (! empty($tz)) {
    1.66 +            if (function_exists('date_default_timezone_set')) {
    1.67 +                if (! @date_default_timezone_set($tz)) {
    1.68 +                    date_default_timezone_set('UTC');
    1.69 +                    COM_errorLog("Timezone '$tz' not valid - using 'UTC' instead", 1);
    1.70 +                }
    1.71 +            } elseif (!ini_get('safe_mode') && function_exists('putenv')) {
    1.72 +                // aka "Timezone Hack"
    1.73 +                putenv('TZ=' . $tz);
    1.74 +            }
    1.75 +        } elseif (function_exists('date_default_timezone_get')) {
    1.76 +            // this is not ideal but will stop PHP 5.3.0ff from complaining ...
    1.77 +            date_default_timezone_set(@date_default_timezone_get());
    1.78 +        }
    1.79 +    }
    1.80 +
    1.81 +    /**
    1.82 +    * Get the user's preferred timezone
    1.83 +    *
    1.84 +    * @return   string  name of the timezone
    1.85 +    * @static
    1.86 +    *
    1.87 +    */
    1.88 +    function getUserTimeZone()
    1.89 +    {
    1.90 +        global $_CONF, $_USER;
    1.91 +
    1.92 +        if (! empty($_USER['tzid'])) {
    1.93 +            $timezone = $_USER['tzid'];
    1.94 +        } elseif (! empty($_CONF['timezone'])) {
    1.95 +            $timezone = $_CONF['timezone'];
    1.96 +        } else {
    1.97 +            require_once 'Date/TimeZone.php';
    1.98 +
    1.99 +            $tz_obj = Date_TimeZone::getDefault();
   1.100 +            $timezone = $tz_obj->id;
   1.101 +        }
   1.102 +
   1.103 +        return $timezone;
   1.104 +    }
   1.105 +
   1.106 +    /**
   1.107 +    * Provide a dropdown menu of the available timezones
   1.108 +    *
   1.109 +    * @return   string  HTML for the dropdown
   1.110 +    * @static
   1.111 +    *
   1.112 +    */
   1.113 +    function getTimeZoneDropDown($selected = '', $attributes = array())
   1.114 +    {
   1.115 +        $timezones = TimeZoneConfig::listAvailableTimeZones();
   1.116 +
   1.117 +        $selection = '<select';
   1.118 +        foreach ($attributes as $name => $value) {
   1.119 +            $selection .= sprintf(' %s="%s"', $name, $value);
   1.120 +        }
   1.121 +        $selection .= '>' . LB;
   1.122 +
   1.123 +        foreach ($timezones as $tzid => $tzdisplay) {
   1.124 +            $selection .= '<option value="' . $tzid . '"';
   1.125 +            if (!empty($selected) && ($selected == $tzid)) {
   1.126 +                $selection .= ' selected="selected"';
   1.127 +            }
   1.128 +            $selection .= ">$tzdisplay</option>" . LB;
   1.129 +        }
   1.130 +        $selection .= '</select>';
   1.131 +
   1.132 +        return $selection;
   1.133 +    }
   1.134 +
   1.135 +    /**
   1.136 +    * Provide a list of available timezones
   1.137 +    *
   1.138 +    * @return   array   array of (timezone-short-name, timezone-long-name) pairs
   1.139 +    * @static
   1.140 +    *
   1.141 +    */
   1.142 +    function listAvailableTimeZones()
   1.143 +    {
   1.144 +        $timezones = array();
   1.145 +
   1.146 +        // use only timezones that contain one of these
   1.147 +        $useonly = array('Africa', 'America', 'Antarctica', 'Arctic', 'Asia',
   1.148 +                         'Atlantic', 'Australia', 'Europe', 'Indian', 'Pacific',
   1.149 +                         'UTC');
   1.150 +
   1.151 +        // check if we can use the DateTimeZone class
   1.152 +        $useDateTimeZone = false;
   1.153 +        if (class_exists('DateTimeZone') && class_exists('ReflectionClass')) {
   1.154 +            $rc = new ReflectionClass('DateTimeZone');
   1.155 +            if ($rc->hasMethod('listAbbreviations')) {
   1.156 +                $useDateTimeZone = true;
   1.157 +            }
   1.158 +        }
   1.159 +
   1.160 +        if ($useDateTimeZone) {
   1.161 +
   1.162 +            $T = DateTimeZone::listAbbreviations();
   1.163 +            foreach ($T as $tzid => $entries) {
   1.164 +                $shortname = strtoupper($tzid);
   1.165 +                foreach ($entries as $data) {
   1.166 +                    $tzcheck = explode('/', $data['timezone_id']);
   1.167 +                    if (! in_array($tzcheck[0], $useonly)) {
   1.168 +                        continue;
   1.169 +                    }
   1.170 +
   1.171 +                    $hours = $data['offset'] / 3600;
   1.172 +                    $hours = ((int) ($hours * 100) / 100);
   1.173 +                    if ($hours > 0) {
   1.174 +                        $hours = "+$hours";
   1.175 +                    }
   1.176 +
   1.177 +                    $tzcode = str_replace('_', ' ', $data['timezone_id']);
   1.178 +                    $tzcode = htmlspecialchars($tzcode);
   1.179 +                    $formattedTimezone = "$hours, $shortname ($tzcode)";
   1.180 +                    $timezones[$data['timezone_id']] = $formattedTimezone;
   1.181 +                }
   1.182 +            }
   1.183 +
   1.184 +        } else { // DateTimeZone not available - use PEAR Date class
   1.185 +
   1.186 +            require_once 'Date/TimeZone.php';
   1.187 +
   1.188 +            $T = $GLOBALS['_DATE_TIMEZONE_DATA'];
   1.189 +
   1.190 +            foreach ($T as $tzid => $tDetails) {
   1.191 +                $tzcheck = explode('/', $tzid);
   1.192 +                if (! in_array($tzcheck[0], $useonly)) {
   1.193 +                    continue;
   1.194 +                }
   1.195 +                if (!empty($tzcheck[1]) &&
   1.196 +                        (strpos($tzcheck[1], 'Riyadh') === 0)) {
   1.197 +                    // these time zones are based on solar time and not widely
   1.198 +                    // supported - skip
   1.199 +                    continue;
   1.200 +                }
   1.201 +
   1.202 +                $tzcode = str_replace('_', ' ', $tzid);
   1.203 +                $tzcode = htmlspecialchars($tzcode);
   1.204 +                $hours = $tDetails['offset'] / (3600 * 1000);
   1.205 +                $hours = ((int) ($hours * 100) / 100);
   1.206 +                if ($hours > 0) {
   1.207 +                    $hours = "+$hours";
   1.208 +                }
   1.209 +
   1.210 +                $formattedTimezone = "$hours, {$tDetails['shortname']} ($tzcode)";
   1.211 +                $timezones[$tzid] = $formattedTimezone;
   1.212 +            }
   1.213 +
   1.214 +        }
   1.215 +
   1.216 +        uasort($timezones, 'TimeZoneConfig::_sort_by_timezone');
   1.217 +
   1.218 +        return $timezones;
   1.219 +    }
   1.220 +
   1.221 +    /**
   1.222 +    * Helper method: Sort timezone entries
   1.223 +    *
   1.224 +    * @param    string  $tz1    first timezone
   1.225 +    * @param    string  $tz2    second timezone
   1.226 +    * @return   int             0: equal, <0: first<second, >0: first>second
   1.227 +    * @static
   1.228 +    * @access   private
   1.229 +    *
   1.230 +    */
   1.231 +    function _sort_by_timezone($tz1, $tz2)
   1.232 +    {
   1.233 +        $p1 = explode(',', $tz1);
   1.234 +        $p2 = explode(',', $tz2);
   1.235 +
   1.236 +        // compare offsets
   1.237 +        $o1 = $p1[0];
   1.238 +        $o2 = $p2[0];
   1.239 +        if ($o1 != $o2) {
   1.240 +            return ($o1 < $o2 ? -1 : 1);
   1.241 +        }
   1.242 +
   1.243 +        // drop offset, pop timezone name, then add it to the end again
   1.244 +        array_shift($p1);
   1.245 +        $tz1 = trim(implode(',', $p1));
   1.246 +        $p1 = explode(' ', $tz1);
   1.247 +        $x1 = array_shift($p1);
   1.248 +        $p1[] = $x1;
   1.249 +        $tz1 = implode(' ', $p1);
   1.250 +
   1.251 +        array_shift($p2);
   1.252 +        $tz2 = trim(implode(',', $p2));
   1.253 +        $p2 = explode(' ', $tz2);
   1.254 +        $x2 = array_shift($p2);
   1.255 +        $p2[] = $x2;
   1.256 +        $tz2 = implode(' ', $p2);
   1.257 +
   1.258 +        return strcmp($tz1, $tz2);
   1.259 +    }
   1.260 +
   1.261 +}
   1.262 +
   1.263 +?>