Adding support for module shared model. If a module admin exists and there is a file...
[akelos.git] / lib / AkLocalize / AkTimeZone.php
blob2a8b6f103f311a43bef091e3f786b68c9563497a
1 <?php
2 /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
4 // +----------------------------------------------------------------------+
5 // | Akelos Framework - http://www.akelos.org |
6 // +----------------------------------------------------------------------+
7 // | Copyright (c) 2002-2006, Akelos Media, S.L. & Bermi Ferrer Martinez |
8 // | Released under the GNU Lesser General Public License, see LICENSE.txt|
9 // +----------------------------------------------------------------------+
11 /**
12 * @package ActiveSupport
13 * @subpackage I18n-L10n
14 * @author Bermi Ferrer <bermi a.t akelos c.om>
15 * @copyright Copyright (c) 2002-2006, Akelos Media, S.L. http://www.akelos.org
16 * @license GNU Lesser General Public License <http://www.gnu.org/copyleft/lesser.html>
22 /**
23 * A value object representing a time zone. A time zone is simply a named
24 * offset (in seconds) from GMT. Note that two time zone objects are only
25 * equivalent if they have both the same offset, and the same name.
27 * A TimeZone instance may be used to convert a Time value to the corresponding
28 * time zone.
30 * The class also includes a method named all(), which returns a list of all TimeZone objects.
32 class AkTimeZone
34 var $name;
35 var $utc_offset;
36 var $dst;
37 var $zones = array();
38 var $dst_zones = array();
40 /**
41 * Initiates a new AkTimeZone object with the given name and offset. The offset is
42 * the number of seconds that this time zone is offset from UTC (GMT).
44 function init($name, $utc_offset, $dst = false)
46 $this->name = $name;
47 $this->utc_offset = $utc_offset;
48 $this->dst = $dst;
51 /**
52 * Returns the offset of this time zone as a formatted string, of the
53 * format "+HH:MM". If the offset is zero, this returns the empty
54 * string. If $colon is false, a colon will not be inserted into the
55 * result.
57 function getFormattedOffset($colon = true)
59 if($this->utc_offset == 0){
60 return '';
62 $sign = ($this->utc_offset < 0 ? -1 : 1);
63 $hours = abs($this->utc_offset) / 3600;
64 $minutes = (abs($this->utc_offset) % 3600) / 60;
65 return sprintf("%+03d%s%02d", $hours * $sign, $colon ? ":" : "", $minutes);
68 /**
69 * Compute and return the current time, in the time zone represented by
70 * AkTimeZone.
72 function now()
74 return $this->adjust(isset($this->_timestamp) ? $this->_timestamp : Ak::getTimestamp());
77 /**
78 * Return the current date in this time zone.
80 function today()
82 return Ak::getDate($this->now(), Ak::locale('date_format'));
85 /**
86 * Return the current time in this time zone.
88 function time()
90 return Ak::getDate($this->now(), Ak::locale('time_format'));
93 /**
94 * Return the current time in this time zone.
96 function dateTime()
98 return Ak::getDate($this->now(), Ak::locale('date_time_format'));
102 * Adjust the given time to the time zone represented by AkTimeZone.
104 function adjust($time)
106 return $time + $this->utc_offset + ($this->dst && $this->inDst($time, $this->name) ? 3600 : 0) - AK_UTC_OFFSET;
110 * Reinterprets the given time value as a time in the current time
111 * zone, and then adjusts it to return the corresponding time in the
112 * local time zone.
114 function unadjust($time)
116 return $time - $this->utc_offset - ($this->dst && $this->inDst($time, $this->name) ? 3600 : 0) + AK_UTC_OFFSET;
120 * Compare this time zone to the parameter. The two are compared first on
121 * their offsets, and then by name.
123 function compare($zone)
125 $result = $this->utc_offset > $zone->utc_offset ? 1 : ($zone->utc_offset > $this->utc_offset ? -1 : 0);
126 $result = $result == 0 ? strcoll($this->name, $zone->name) : $result;
127 return $result == 0 ? 0 : ($result > 0 ? 1 : -1);
131 * Returns a textual representation of this time zone.
133 function toString()
135 return '(GMT'.$this->getFormattedOffset().") $this->name";
139 function inDst($timestamp, $zone_name)
141 $env_tz = function_exists('date_default_timezone_get') ? @date_default_timezone_get() : @getenv('TZ');
142 function_exists('date_default_timezone_set') ? date_default_timezone_set($zone_name) : @putenv('TZ='.$zone_name);
143 $localtime = localtime($timestamp, true);
144 if(!empty($env_tz)){
145 function_exists('date_default_timezone_set') ? date_default_timezone_set($env_tz) : @putenv('TZ='.$env_tz);
147 return !empty($localtime['tm_isdst']);
152 * Static method for creating new AkTimeZone object with the given name, offset and an options zones array.
154 function create($name, $timezone = null, $zones = null, $dst_zones = null)
156 $Zone = new AkTimeZone();
157 if(!empty($zones)){
158 $Zone->zones = $zones;
160 if(!empty($dst_zones)){
161 $Zone->dst_zones = $dst_zones;
163 $details = $Zone->locateTimezone($name);
164 $details = empty($details) ? $Zone->locateTimezone($timezone) : $details;
165 if(!empty($details)){
166 $name = $details['name'];
167 $timezone = $details['offset'];
169 $Zone->init($name, $timezone, !empty($Zone->dst_zones) && in_array($name, $Zone->dst_zones));
170 unset($Zone->zones, $Zone->dst_zones);
171 return $Zone;
175 * Locate a specific time zone. If the argument is a string, it
176 * is interpreted to mean the name of the timezone to locate. If it is a
177 * numeric value it is either the hour offset, or the second offset, of the
178 * timezone to find. (The first one with that offset will be returned.)
179 * Returns false if no such time zone is known to the system.
181 function locateTimezone($timezone_name_or_offset)
183 if(is_string($timezone_name_or_offset)){
184 $timezones = $this->getTimezones();
185 if(isset($timezones[$timezone_name_or_offset])){
186 return array('offset'=>$timezones[$timezone_name_or_offset], 'name' => $timezone_name_or_offset);
188 }elseif (is_numeric($timezone_name_or_offset)){
189 $timezones = $this->getTimezones();
190 foreach ($timezones as $zone => $offset){
191 if($timezone_name_or_offset == $offset){
192 return array('offset'=>$offset, 'name' => $zone);
195 }else{
196 trigger_error(Ak::t('Invalid argument at AkTimeZone::locateTimezone(), you must supply a Time zone name or offset'), E_USER_NOTICE);
198 return false;
202 * Return an array of all time zones, as Place => Offset. There are multiple
203 * places per time zone, in many cases, to make it easier for users to
204 * find their own time zone.
206 * Places prefixed with "-" are those who have DST in the South Hemisphere
208 function getTimezones()
210 if(empty($this->zones)){
211 $zones = Ak::t(
212 '-43200 | Etc/GMT+12
213 -39600 | Etc/GMT+11, MIT, Pacific/Apia, Pacific/Midway, Pacific/Niue, Pacific/Pago Pago, Pacific/Samoa, US/Samoa
214 -36000 | -America/Adak, -America/Atka, Etc/GMT+10, HST, Pacific/Fakaofo, Pacific/Honolulu, Pacific/Johnston, Pacific/Rarotonga, Pacific/Tahiti, SystemV/HST10, -US/Aleutian, US/Hawaii
215 -34200 | Pacific/Marquesas
216 -32400 | -AST, -America/Anchorage, -America/Juneau, -America/Nome, -America/Yakutat, Etc/GMT+9, Pacific/Gambier, SystemV/YST9, -SystemV/YST9YDT, -US/Alaska
217 -28800 | -America/Dawson, -America/Ensenada, -America/Los Angeles, -America/Tijuana, -America/Vancouver, -America/Whitehorse, -Canada/Pacific, -Canada/Yukon, Etc/GMT+8, -Mexico/BajaNorte, -PST, -PST8PDT, Pacific/Pitcairn, SystemV/PST8, -SystemV/PST8PDT, -US/Pacific, -US/Pacific-New
218 -25200 | -America/Boise, -America/Cambridge Bay, -America/Chihuahua, America/Dawson Creek, -America/Denver, -America/Edmonton, America/Hermosillo, -America/Inuvik, -America/Mazatlan, America/Phoenix, -America/Shiprock, -America/Yellowknife, -Canada/Mountain, Etc/GMT+7, -MST, -MST7MDT, -Mexico/BajaSur, -Navajo, PNT, SystemV/MST7, -SystemV/MST7MDT, US/Arizona, -US/Mountain
219 -21600 | America/Belize, -America/Cancun, -America/Chicago, America/Costa Rica, America/El Salvador, America/Guatemala, America/Managua, -America/Menominee, -America/Merida, America/Mexico City, -America/Monterrey, -America/North Dakota/Center, -America/Rainy River, -America/Rankin Inlet, America/Regina, America/Swift Current, America/Tegucigalpa, -America/Winnipeg, -CST, -CST6CDT, -Canada/Central, Canada/East-Saskatchewan, Canada/Saskatchewan, -Chile/EasterIsland, Etc/GMT+6, Mexico/General, -Pacific/Easter, Pacific/Galapagos, SystemV/CST6, -SystemV/CST6CDT, -US/Central
220 -18000 | America/Bogota, America/Cayman, -America/Detroit, America/Eirunepe, America/Fort Wayne, -America/Grand Turk, America/Guayaquil, -America/Havana, America/Indiana/Indianapolis, America/Indiana/Knox, America/Indiana/Marengo, America/Indiana/Vevay, America/Indianapolis, -America/Iqaluit, America/Jamaica, -America/Kentucky/Louisville, -America/Kentucky/Monticello, America/Knox IN, America/Lima, -America/Louisville, -America/Montreal, -America/Nassau, -America/New York, -America/Nipigon, America/Panama, -America/Pangnirtung, America/Port-au-Prince, America/Porto Acre, America/Rio Branco, -America/Thunder Bay, Brazil/Acre, -Canada/Eastern, -Cuba, -EST, -EST5EDT, Etc/GMT+5, IET, Jamaica, SystemV/EST5, -SystemV/EST5EDT, US/East-Indiana, -US/Eastern, US/Indiana-Starke, -US/Michigan
221 -14400 | America/Anguilla, America/Antigua, America/Aruba, -America/Asuncion, America/Barbados, America/Boa Vista, America/Caracas, -America/Cuiaba, America/Curacao, America/Dominica, -America/Glace Bay, -America/Goose Bay, America/Grenada, America/Guadeloupe, America/Guyana, -America/Halifax, America/La Paz, America/Manaus, America/Martinique, America/Montserrat, America/Port of Spain, America/Porto Velho, America/Puerto Rico, -America/Santiago, America/Santo Domingo, America/St Kitts, America/St Lucia, America/St Thomas, America/St Vincent, America/Thule, America/Tortola, America/Virgin, -Antarctica/Palmer, -Atlantic/Bermuda, -Atlantic/Stanley, Brazil/West, -Canada/Atlantic, -Chile/Continental, Etc/GMT+4, PRT, SystemV/AST4, -SystemV/AST4ADT
222 -12600 | -America/St Johns, -CNT, -Canada/Newfoundland
223 -10800 | AGT, -America/Araguaina, America/Belem, America/Buenos Aires, America/Catamarca, America/Cayenne, America/Cordoba, -America/Fortaleza, -America/Godthab, America/Jujuy, -America/Maceio, America/Mendoza, -America/Miquelon, America/Montevideo, America/Paramaribo, -America/Recife, America/Rosario, -America/Sao Paulo, -BET, -Brazil/East, Etc/GMT+3
224 -7200 | America/Noronha, Atlantic/South Georgia, Brazil/DeNoronha, Etc/GMT+2
225 -3600 | -America/Scoresbysund, -Atlantic/Azores, Atlantic/Cape Verde, Etc/GMT+1
226 0 | Africa/Abidjan, Africa/Accra, Africa/Bamako, Africa/Banjul, Africa/Bissau, Africa/Casablanca, Africa/Conakry, Africa/Dakar, Africa/El Aaiun, Africa/Freetown, Africa/Lome, Africa/Monrovia, Africa/Nouakchott, Africa/Ouagadougou, Africa/Sao Tome, Africa/Timbuktu, America/Danmarkshavn, -Atlantic/Canary, -Atlantic/Faeroe, -Atlantic/Madeira, Atlantic/Reykjavik, Atlantic/St Helena, -Eire, Etc/GMT, Etc/GMT+0, Etc/GMT-0, Etc/GMT0, Etc/Greenwich, Etc/UCT, Etc/UTC, Etc/Universal, Etc/Zulu, -Europe/Belfast, -Europe/Dublin, -Europe/Lisbon, -Europe/London, -GB, -GB-Eire, GMT, GMT0, Greenwich, Iceland, -Portugal, UCT, UTC, Universal, -WET, Zulu
227 3600 | Africa/Algiers, Africa/Bangui, Africa/Brazzaville, -Africa/Ceuta, Africa/Douala, Africa/Kinshasa, Africa/Lagos, Africa/Libreville, Africa/Luanda, Africa/Malabo, Africa/Ndjamena, Africa/Niamey, Africa/Porto-Novo, Africa/Tunis, -Africa/Windhoek, -Arctic/Longyearbyen, -Atlantic/Jan Mayen, -CET, -ECT, Etc/GMT-1, -Europe/Amsterdam, -Europe/Andorra, -Europe/Belgrade, -Europe/Berlin, -Europe/Bratislava, -Europe/Brussels, -Europe/Budapest, -Europe/Copenhagen, -Europe/Gibraltar, -Europe/Ljubljana, -Europe/Luxembourg, -Europe/Madrid, -Europe/Malta, -Europe/Monaco, -Europe/Oslo, -Europe/Paris, -Europe/Prague, -Europe/Rome, -Europe/San Marino, -Europe/Sarajevo, -Europe/Skopje, -Europe/Stockholm, -Europe/Tirane, -Europe/Vaduz, -Europe/Vatican, -Europe/Vienna, -Europe/Warsaw, -Europe/Zagreb, -Europe/Zurich, -MET, -Poland
228 7200 | -ART, Africa/Blantyre, Africa/Bujumbura, -Africa/Cairo, Africa/Gaborone, Africa/Harare, Africa/Johannesburg, Africa/Kigali, Africa/Lubumbashi, Africa/Lusaka, Africa/Maputo, Africa/Maseru, Africa/Mbabane, Africa/Tripoli, -Asia/Amman, -Asia/Beirut, -Asia/Damascus, -Asia/Gaza, -Asia/Istanbul, -Asia/Jerusalem, -Asia/Nicosia, -Asia/Tel Aviv, CAT, -EET, -Egypt, Etc/GMT-2, -Europe/Athens, -Europe/Bucharest, -Europe/Chisinau, -Europe/Helsinki, -Europe/Istanbul, -Europe/Kaliningrad, -Europe/Kiev, -Europe/Minsk, -Europe/Nicosia, -Europe/Riga, -Europe/Simferopol, -Europe/Sofia, Europe/Tallinn, -Europe/Tiraspol, -Europe/Uzhgorod, Europe/Vilnius, -Europe/Zaporozhye, -Israel, Libya, -Turkey
229 10800 | Africa/Addis Ababa, Africa/Asmera, Africa/Dar es Salaam, Africa/Djibouti, Africa/Kampala, Africa/Khartoum, Africa/Mogadishu, Africa/Nairobi, Antarctica/Syowa, Asia/Aden, -Asia/Baghdad, Asia/Bahrain, Asia/Kuwait, Asia/Qatar, Asia/Riyadh, EAT, Etc/GMT-3, -Europe/Moscow, Indian/Antananarivo, Indian/Comoro, Indian/Mayotte, -W-SU
230 11224 | Asia/Riyadh87, Asia/Riyadh88, Asia/Riyadh89, Mideast/Riyadh87, Mideast/Riyadh88, Mideast/Riyadh89
231 12600 | -Asia/Tehran, -Iran
232 14400 | -Asia/Aqtau, -Asia/Baku, Asia/Dubai, Asia/Muscat, -Asia/Tbilisi, -Asia/Yerevan, Etc/GMT-4, -Europe/Samara, Indian/Mahe, Indian/Mauritius, Indian/Reunion, -NET
233 16200 | Asia/Kabul
234 18000 | -Asia/Aqtobe, Asia/Ashgabat, Asia/Ashkhabad, -Asia/Bishkek, Asia/Dushanbe, Asia/Karachi, Asia/Samarkand, Asia/Tashkent, -Asia/Yekaterinburg, Etc/GMT-5, Indian/Kerguelen, Indian/Maldives, PLT
235 19800 | Asia/Calcutta, IST
236 20700 | Asia/Katmandu
237 21600 | Antarctica/Mawson, Antarctica/Vostok, -Asia/Almaty, Asia/Colombo, Asia/Dacca, Asia/Dhaka, -Asia/Novosibirsk, -Asia/Omsk, Asia/Thimbu, Asia/Thimphu, BST, Etc/GMT-6, Indian/Chagos
238 23400 | Asia/Rangoon, Indian/Cocos
239 25200 | Antarctica/Davis, Asia/Bangkok, Asia/Hovd, Asia/Jakarta, -Asia/Krasnoyarsk, Asia/Phnom Penh, Asia/Pontianak, Asia/Saigon, Asia/Vientiane, Etc/GMT-7, Indian/Christmas, VST
240 28800 | Antarctica/Casey, Asia/Brunei, Asia/Chongqing, Asia/Chungking, Asia/Harbin, Asia/Hong Kong, -Asia/Irkutsk, Asia/Kashgar, Asia/Kuala Lumpur, Asia/Kuching, Asia/Macao, Asia/Manila, Asia/Shanghai, Asia/Singapore, Asia/Taipei, Asia/Ujung Pandang, Asia/Ulaanbaatar, Asia/Ulan Bator, Asia/Urumqi, Australia/Perth, Australia/West, CTT, Etc/GMT-8, Hongkong, PRC, Singapore
241 32400 | Asia/Choibalsan, Asia/Dili, Asia/Jayapura, Asia/Pyongyang, Asia/Seoul, Asia/Tokyo, -Asia/Yakutsk, Etc/GMT-9, JST, Japan, Pacific/Palau, ROK
242 34200 | ACT, -Australia/Adelaide, -Australia/Broken Hill, Australia/Darwin, Australia/North, -Australia/South, -Australia/Yancowinna
243 36000 | -AET, Antarctica/DumontDUrville, -Asia/Sakhalin, -Asia/Vladivostok, -Australia/ACT, Australia/Brisbane, -Australia/Canberra, -Australia/Hobart, Australia/Lindeman, -Australia/Melbourne, -Australia/NSW, Australia/Queensland, -Australia/Sydney, -Australia/Tasmania, -Australia/Victoria, Etc/GMT-10, Pacific/Guam, Pacific/Port Moresby, Pacific/Saipan, Pacific/Truk, Pacific/Yap
244 37800 | -Australia/LHI, -Australia/Lord Howe
245 39600 | -Asia/Magadan, Etc/GMT-11, Pacific/Efate, Pacific/Guadalcanal, Pacific/Kosrae, Pacific/Noumea, Pacific/Ponape, SST
246 41400 | Pacific/Norfolk
247 43200 | -Antarctica/McMurdo, -Antarctica/South Pole, -Asia/Anadyr, -Asia/Kamchatka, Etc/GMT-12, Kwajalein, -NST, -NZ, -Pacific/Auckland, Pacific/Fiji, Pacific/Funafuti, Pacific/Kwajalein, Pacific/Majuro, Pacific/Nauru, Pacific/Tarawa, Pacific/Wake, Pacific/Wallis
248 45900 | -NZ-CHAT, -Pacific/Chatham
249 46800 | Etc/GMT-13, Pacific/Enderbury, Pacific/Tongatapu
250 50400 | Etc/GMT-14, Pacific/Kiritimati', null, 'localize/timezone');
252 $this->zones = array();
253 foreach (explode("\n", $zones) as $zone){
254 list($offset, $places) = explode('|', $zone);
255 $offset = intval($offset);
256 $places = array_map('trim', array_diff(explode(',', $places.','), array('')));
257 foreach ($places as $k=>$place){
258 if($place[0] == '-'){
259 $places[$k] = trim($place,'-');
260 $this->dst_zones[] = $places[$k];
263 sort($places);
264 foreach ($places as $place){
265 $this->zones[$place] = $offset;
270 return $this->zones;
274 * Return an array of all AkTimeZone objects. There are multiple AkTimeZone objects
275 * per time zone, in many cases, to make it easier for users to find their own time zone.
277 function &all()
279 $TimeZone = new AkTimeZone();
280 $time_zones = $TimeZone->getTimezones();
281 $dst_zones = $TimeZone->dst_zones;
282 $Zones = array();
283 foreach ($time_zones as $name => $offset){
284 $Zones[] = $TimeZone->create($name, $offset, $time_zones, $dst_zones);
286 return $Zones;
290 defined('AK_DEFAULT_TIMEZONE') ? null : define('AK_DEFAULT_TIMEZONE', 'UTC');
292 function_exists('date_default_timezone_set') ? date_default_timezone_set(AK_DEFAULT_TIMEZONE) : @putenv('TZ='.AK_DEFAULT_TIMEZONE);
294 if(!defined('AK_UTC_OFFSET')){
295 $_AkCurrentZone = new AkTimeZone();
296 $_AkCurrentZone = $_AkCurrentZone->create(AK_DEFAULT_TIMEZONE);
297 define('AK_UTC_OFFSET', $_AkCurrentZone->utc_offset);
298 unset($_AkCurrentZone);