1<?php 2/*********************************************** 3* File : timezoneutil.php 4* Project : Z-Push 5* Descr : class to generate AS compatible timezone information 6* 7* Created : 01.06.2012 8* 9* Copyright 2007 - 2016 Zarafa Deutschland GmbH 10* 11* This program is free software: you can redistribute it and/or modify 12* it under the terms of the GNU Affero General Public License, version 3, 13* as published by the Free Software Foundation. 14* 15* This program is distributed in the hope that it will be useful, 16* but WITHOUT ANY WARRANTY; without even the implied warranty of 17* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18* GNU Affero General Public License for more details. 19* 20* You should have received a copy of the GNU Affero General Public License 21* along with this program. If not, see <http://www.gnu.org/licenses/>. 22* 23* Consult LICENSE file for details 24************************************************/ 25 26class TimezoneUtil { 27 28 /** 29 * list of MS and AS compatible timezones 30 * 31 * origin: http://msdn.microsoft.com/en-us/library/ms912391%28v=winembedded.11%29.aspx 32 * dots of tz identifiers were removed 33 * 34 * Updated at: 01.06.2012 35 */ 36 private static $mstzones = array( 37 "000" => array("Dateline Standard Time", "(GMT-12:00) International Date Line West"), 38 "001" => array("Samoa Standard Time", "(GMT-11:00) Midway Island, Samoa"), 39 "002" => array("Hawaiian Standard Time", "(GMT-10:00) Hawaii"), 40 "003" => array("Alaskan Standard Time", "(GMT-09:00) Alaska"), 41 "004" => array("Pacific Standard Time", "(GMT-08:00) Pacific Time (US and Canada); Tijuana"), 42 "010" => array("Mountain Standard Time", "(GMT-07:00) Mountain Time (US and Canada)"), 43 "013" => array("Mexico Standard Time 2", "(GMT-07:00) Chihuahua, La Paz, Mazatlan"), 44 "015" => array("US Mountain Standard Time", "(GMT-07:00) Arizona"), 45 "020" => array("Central Standard Time", "(GMT-06:00) Central Time (US and Canada"), 46 "025" => array("Canada Central Standard Time", "(GMT-06:00) Saskatchewan"), 47 "030" => array("Mexico Standard Time", "(GMT-06:00) Guadalajara, Mexico City, Monterrey"), 48 "033" => array("Central America Standard Time", "(GMT-06:00) Central America"), 49 "035" => array("Eastern Standard Time", "(GMT-05:00) Eastern Time (US and Canada)"), 50 "040" => array("US Eastern Standard Time", "(GMT-05:00) Indiana (East)"), 51 "045" => array("SA Pacific Standard Time", "(GMT-05:00) Bogota, Lima, Quito"), 52 "uk1" => array("Venezuela Standard Time", "(GMT-04:30) Caracas"), // added 53 "050" => array("Atlantic Standard Time", "(GMT-04:00) Atlantic Time (Canada)"), 54 "055" => array("SA Western Standard Time", "(GMT-04:00) Caracas, La Paz"), 55 "056" => array("Pacific SA Standard Time", "(GMT-04:00) Santiago"), 56 "060" => array("Newfoundland and Labrador Standard Time", "(GMT-03:30) Newfoundland and Labrador"), 57 "065" => array("E South America Standard Time" , "(GMT-03:00) Brasilia"), 58 "070" => array("SA Eastern Standard Time", "(GMT-03:00) Buenos Aires, Georgetown"), 59 "073" => array("Greenland Standard Time", "(GMT-03:00) Greenland"), 60 "075" => array("Mid-Atlantic Standard Time", "(GMT-02:00) Mid-Atlantic"), 61 "080" => array("Azores Standard Time", "(GMT-01:00) Azores"), 62 "083" => array("Cape Verde Standard Time", "(GMT-01:00) Cape Verde Islands"), 63 "085" => array("GMT Standard Time", "(GMT) Greenwich Mean Time: Dublin, Edinburgh, Lisbon, London"), 64 "090" => array("Greenwich Standard Time", "(GMT) Casablanca, Monrovia"), 65 "095" => array("Central Europe Standard Time", "(GMT+01:00) Belgrade, Bratislava, Budapest, Ljubljana, Prague"), 66 "100" => array("Central European Standard Time", "(GMT+01:00) Sarajevo, Skopje, Warsaw, Zagreb"), 67 "105" => array("Romance Standard Time", "(GMT+01:00) Brussels, Copenhagen, Madrid, Paris"), 68 "110" => array("W Europe Standard Time", "(GMT+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna"), 69 "111" => array("W. Europe Standard Time", "(GMT+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna"), 70 "113" => array("W Central Africa Standard Time", "(GMT+01:00) West Central Africa"), 71 "115" => array("E Europe Standard Time", "(GMT+02:00) Bucharest"), 72 "120" => array("Egypt Standard Time", "(GMT+02:00) Cairo"), 73 "125" => array("FLE Standard Time", "(GMT+02:00) Helsinki, Kiev, Riga, Sofia, Tallinn, Vilnius"), 74 "130" => array("GTB Standard Time", "(GMT+02:00) Athens, Istanbul, Minsk"), 75 "135" => array("Israel Standard Time", "(GMT+02:00) Jerusalem"), 76 "140" => array("South Africa Standard Time", "(GMT+02:00) Harare, Pretoria"), 77 "145" => array("Russian Standard Time", "(GMT+03:00) Moscow, St. Petersburg, Volgograd"), 78 "150" => array("Arab Standard Time", "(GMT+03:00) Kuwait, Riyadh"), 79 "155" => array("E Africa Standard Time", "(GMT+03:00) Nairobi"), 80 "158" => array("Arabic Standard Time", "(GMT+03:00) Baghdad"), 81 "160" => array("Iran Standard Time", "(GMT+03:30) Tehran"), 82 "165" => array("Arabian Standard Time", "(GMT+04:00) Abu Dhabi, Muscat"), 83 "170" => array("Caucasus Standard Time", "(GMT+04:00) Baku, Tbilisi, Yerevan"), 84 "175" => array("Transitional Islamic State of Afghanistan Standard Time","(GMT+04:30) Kabul"), 85 "180" => array("Ekaterinburg Standard Time", "(GMT+05:00) Ekaterinburg"), 86 "185" => array("West Asia Standard Time", "(GMT+05:00) Islamabad, Karachi, Tashkent"), 87 "190" => array("India Standard Time", "(GMT+05:30) Chennai, Kolkata, Mumbai, New Delhi"), 88 "193" => array("Nepal Standard Time", "(GMT+05:45) Kathmandu"), 89 "195" => array("Central Asia Standard Time", "(GMT+06:00) Astana, Dhaka"), 90 "200" => array("Sri Lanka Standard Time", "(GMT+06:00) Sri Jayawardenepura"), 91 "201" => array("N Central Asia Standard Time", "(GMT+06:00) Almaty, Novosibirsk"), 92 "203" => array("Myanmar Standard Time", "(GMT+06:30) Yangon Rangoon"), 93 "205" => array("SE Asia Standard Time", "(GMT+07:00) Bangkok, Hanoi, Jakarta"), 94 "207" => array("North Asia Standard Time", "(GMT+07:00) Krasnoyarsk"), 95 "210" => array("China Standard Time", "(GMT+08:00) Beijing, Chongqing, Hong Kong SAR, Urumqi"), 96 "215" => array("Singapore Standard Time", "(GMT+08:00) Kuala Lumpur, Singapore"), 97 "220" => array("Taipei Standard Time", "(GMT+08:00) Taipei"), 98 "225" => array("W Australia Standard Time", "(GMT+08:00) Perth"), 99 "227" => array("North Asia East Standard Time", "(GMT+08:00) Irkutsk, Ulaanbaatar"), 100 "230" => array("Korea Standard Time", "(GMT+09:00) Seoul"), 101 "235" => array("Tokyo Standard Time", "(GMT+09:00) Osaka, Sapporo, Tokyo"), 102 "240" => array("Yakutsk Standard Time", "(GMT+09:00) Yakutsk"), 103 "245" => array("AUS Central Standard Time", "(GMT+09:30) Darwin"), 104 "250" => array("Cen Australia Standard Time", "(GMT+09:30) Adelaide"), 105 "255" => array("AUS Eastern Standard Time", "(GMT+10:00) Canberra, Melbourne, Sydney"), 106 "260" => array("E Australia Standard Time", "(GMT+10:00) Brisbane"), 107 "265" => array("Tasmania Standard Time", "(GMT+10:00) Hobart"), 108 "270" => array("Vladivostok Standard Time", "(GMT+10:00) Vladivostok"), 109 "275" => array("West Pacific Standard Time", "(GMT+10:00) Guam, Port Moresby"), 110 "280" => array("Central Pacific Standard Time", "(GMT+11:00) Magadan, Solomon Islands, New Caledonia"), 111 "285" => array("Fiji Islands Standard Time", "(GMT+12:00) Fiji Islands, Kamchatka, Marshall Islands"), 112 "290" => array("New Zealand Standard Time", "(GMT+12:00) Auckland, Wellington"), 113 "300" => array("Tonga Standard Time", "(GMT+13:00) Nuku'alofa"), 114 ); 115 116 /** 117 * Python generated offset list 118 * dots in keys were removed 119 * 120 * Array indices 121 * 0 = lBias 122 * 1 = lStandardBias 123 * 2 = lDSTBias 124 * 3 = wStartYear 125 * 4 = wStartMonth 126 * 5 = wStartDOW 127 * 6 = wStartDay 128 * 7 = wStartHour 129 * 8 = wStartMinute 130 * 9 = wStartSecond 131 * 10 = wStartMilliseconds 132 * 11 = wEndYear 133 * 12 = wEndMonth 134 * 13 = wEndDOW 135 * 14 = wEndDay 136 * 15 = wEndHour 137 * 16 = wEndMinute 138 * 17 = wEndSecond 139 * 18 = wEndMilloseconds 140 * 141 * As the $tzoneoffsets and the $mstzones need to be resolved in both directions, 142 * some offsets are commented as they are not available in the $mstzones. 143 * 144 * Created at: 01.06.2012 145 */ 146 private static $tzonesoffsets = array( 147 "Transitional Islamic State of Afghanistan Standard Time" 148 => array(-270, 0, -60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 149 "Alaskan Standard Time" => array(540, 0, -60, 0, 11, 0, 1, 2, 0, 0, 0, 0, 3, 0, 2, 2, 0, 0, 0), 150 "Arab Standard Time" => array(-180, 0, -60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 151 "Arabian Standard Time" => array(-240, 0, -60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 152 "Arabic Standard Time" => array(-180, 0, -60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 153 //"Argentina Standard Time" => array(180, 0, -60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 154 "Atlantic Standard Time" => array(240, 0, -60, 0, 11, 0, 1, 2, 0, 0, 0, 0, 3, 0, 2, 2, 0, 0, 0), 155 "AUS Central Standard Time" => array(-570, 0, -60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 156 "AUS Eastern Standard Time" => array(-600, 0, -60, 0, 4, 0, 1, 3, 0, 0, 0, 0, 10, 0, 1, 2, 0, 0, 0), 157 //"Azerbaijan Standard Time" => array(-240, 0, -60, 0, 10, 0, 5, 5, 0, 0, 0, 0, 3, 0, 5, 4, 0, 0, 0), 158 "Azores Standard Time" => array(60, 0, -60, 0, 10, 0, 5, 3, 0, 0, 0, 0, 3, 0, 5, 2, 0, 0, 0), 159 //"Bangladesh Standard Time" => array(-360, 0, -60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 160 "Canada Central Standard Time" => array(360, 0, -60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 161 "Cape Verde Standard Time" => array(60, 0, -60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 162 "Caucasus Standard Time" => array(-240, 0, -60, 0, 10, 0, 5, 3, 0, 0, 0, 0, 3, 0, 5, 2, 0, 0, 0), 163 "Cen Australia Standard Time" => array(-570, 0, -60, 0, 4, 0, 1, 3, 0, 0, 0, 0, 10, 0, 1, 2, 0, 0, 0), 164 "Central America Standard Time" => array(360, 0, -60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 165 "Central Asia Standard Time" => array(-360, 0, -60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 166 //"Central Brazilian Standard Time" => array(240, 0, -60, 0, 2, 6, 4, 23, 59, 59, 999, 0, 10, 6, 3, 23, 59, 59, 999), 167 "Central Europe Standard Time" => array(-60, 0, -60, 0, 10, 0, 5, 3, 0, 0, 0, 0, 3, 0, 5, 2, 0, 0, 0), 168 "Central European Standard Time" => array(-60, 0, -60, 0, 10, 0, 5, 3, 0, 0, 0, 0, 3, 0, 5, 2, 0, 0, 0), 169 "Central Pacific Standard Time" => array(-660, 0, -60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 170 "Central Standard Time" => array(360, 0, -60, 0, 11, 0, 1, 2, 0, 0, 0, 0, 3, 0, 2, 2, 0, 0, 0), 171 "Mexico Standard Time" => array(360, 0, -60, 0, 10, 0, 5, 2, 0, 0, 0, 0, 4, 0, 1, 2, 0, 0, 0), 172 "China Standard Time" => array(-480, 0, -60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 173 "Dateline Standard Time" => array(720, 0, -60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 174 "E Africa Standard Time" => array(-180, 0, -60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 175 "E Australia Standard Time" => array(-600, 0, -60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 176 "E Europe Standard Time" => array(-120, 0, -60, 0, 10, 0, 5, 3, 0, 0, 0, 0, 3, 0, 5, 2, 0, 0, 0), 177 "E South America Standard Time" => array(180, 0, -60, 0, 2, 6, 4, 23, 59, 59, 999, 0, 10, 6, 3, 23, 59, 59, 999), 178 "Eastern Standard Time" => array(300, 0, -60, 0, 11, 0, 1, 2, 0, 0, 0, 0, 3, 0, 2, 2, 0, 0, 0), 179 "Egypt Standard Time" => array(-120, 0, -60, 0, 9, 4, 5, 23, 59, 59, 999, 0, 4, 4, 5, 23, 59, 59, 999), 180 "Ekaterinburg Standard Time" => array(-300, 0, -60, 0, 10, 0, 5, 3, 0, 0, 0, 0, 3, 0, 5, 2, 0, 0, 0), 181 "Fiji Islands Standard Time" => array(-720, 0, -60, 0, 3, 0, 5, 3, 0, 0, 0, 0, 10, 0, 4, 2, 0, 0, 0), 182 "FLE Standard Time" => array(-120, 0, -60, 0, 10, 0, 5, 4, 0, 0, 0, 0, 3, 0, 5, 3, 0, 0, 0), 183 //"Georgian Standard Time" => array(-240, 0, -60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 184 "GMT Standard Time" => array(0, 0, -60, 0, 10, 0, 5, 2, 0, 0, 0, 0, 3, 0, 5, 1, 0, 0, 0), 185 "Greenland Standard Time" => array(180, 0, -60, 0, 10, 6, 5, 23, 0, 0, 0, 0, 3, 6, 4, 22, 0, 0, 0), 186 "Greenwich Standard Time" => array(0, 0, -60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 187 "GTB Standard Time" => array(-120, 0, -60, 0, 10, 0, 5, 4, 0, 0, 0, 0, 3, 0, 5, 3, 0, 0, 0), 188 "Hawaiian Standard Time" => array(600, 0, -60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 189 "India Standard Time" => array(-330, 0, -60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 190 "Iran Standard Time" => array(-210, 0, -60, 0, 9, 1, 3, 23, 59, 59, 999, 0, 3, 6, 3, 23, 59, 59, 999), 191 "Israel Standard Time" => array(-120, 0, -60, 0, 9, 0, 4, 2, 0, 0, 0, 0, 3, 5, 5, 2, 0, 0, 0), 192 //"Jordan Standard Time" => array(-120, 0, -60, 0, 10, 5, 5, 1, 0, 0, 0, 0, 3, 4, 5, 23, 59, 59, 999), 193 //"Kamchatka Standard Time" => array(-720, 0, -60, 0, 10, 0, 5, 3, 0, 0, 0, 0, 3, 0, 5, 2, 0, 0, 0), 194 "Korea Standard Time" => array(-540, 0, -60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 195 //"Magadan Standard Time" => array(-660, 0, -60, 0, 10, 0, 5, 3, 0, 0, 0, 0, 3, 0, 5, 2, 0, 0, 0), 196 //"Mauritius Standard Time" => array(-240, 0, -60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 197 "Mid-Atlantic Standard Time" => array(120, 0, -60, 0, 9, 0, 5, 2, 0, 0, 0, 0, 3, 0, 5, 2, 0, 0, 0), 198 //"Middle East Standard Time" => array(-120, 0, -60, 0, 10, 6, 5, 23, 59, 59, 999, 0, 3, 6, 4, 23, 59, 59, 999), 199 //"Montevideo Standard Time" => array(180, 0, -60, 0, 3, 0, 2, 2, 0, 0, 0, 0, 10, 0, 1, 2, 0, 0, 0), 200 //"Morocco Standard Time" => array(0, 0, -60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 201 "Mountain Standard Time" => array(420, 0, -60, 0, 11, 0, 1, 2, 0, 0, 0, 0, 3, 0, 2, 2, 0, 0, 0), 202 "Mexico Standard Time 2" => array(420, 0, -60, 0, 10, 0, 5, 2, 0, 0, 0, 0, 4, 0, 1, 2, 0, 0, 0), 203 "Myanmar Standard Time" => array(-390, 0, -60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 204 "N Central Asia Standard Time" => array(-360, 0, -60, 0, 10, 0, 5, 3, 0, 0, 0, 0, 3, 0, 5, 2, 0, 0, 0), 205 //"Namibia Standard Time" => array(-60, 0, -60, 0, 4, 0, 1, 2, 0, 0, 0, 0, 9, 0, 1, 2, 0, 0, 0), 206 "Nepal Standard Time" => array(-345, 0, -60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 207 "New Zealand Standard Time" => array(-720, 0, -60, 0, 4, 0, 1, 3, 0, 0, 0, 0, 9, 0, 5, 2, 0, 0, 0), 208 "Newfoundland and Labrador Standard Time" => array(210, 0, -60, 0, 11, 0, 1, 0, 1, 0, 0, 0, 3, 0, 2, 0, 1, 0, 0), 209 "North Asia East Standard Time" => array(-480, 0, -60, 0, 10, 0, 5, 3, 0, 0, 0, 0, 3, 0, 5, 2, 0, 0, 0), 210 "North Asia Standard Time" => array(-420, 0, -60, 0, 10, 0, 5, 3, 0, 0, 0, 0, 3, 0, 5, 2, 0, 0, 0), 211 "Pacific SA Standard Time" => array(240, 0, -60, 0, 3, 6, 2, 23, 59, 59, 999, 0, 10, 6, 2, 23, 59, 59, 999), 212 "Pacific Standard Time" => array(480, 0, -60, 0, 11, 0, 1, 2, 0, 0, 0, 0, 3, 0, 2, 2, 0, 0, 0), 213 //"Pacific Standard Time (Mexico)" => array(480, 0, -60, 0, 10, 0, 5, 2, 0, 0, 0, 0, 4, 0, 1, 2, 0, 0, 0), 214 //"Pakistan Standard Time" => array(-300, 0, -60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 215 //"Paraguay Standard Time" => array(240, 0, -60, 0, 4, 6, 1, 23, 59, 59, 999, 0, 10, 6, 1, 23, 59, 59, 999), 216 "Romance Standard Time" => array(-60, 0, -60, 0, 10, 0, 5, 3, 0, 0, 0, 0, 3, 0, 5, 2, 0, 0, 0), 217 "Russian Standard Time" => array(-180, 0, -60, 0, 10, 0, 5, 3, 0, 0, 0, 0, 3, 0, 5, 2, 0, 0, 0), 218 "SA Eastern Standard Time" => array(180, 0, -60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 219 "SA Pacific Standard Time" => array(300, 0, -60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 220 "SA Western Standard Time" => array(240, 0, -60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 221 "Samoa Standard Time" => array(660, 0, -60, 0, 3, 6, 5, 23, 59, 59, 999, 0, 9, 6, 5, 23, 59, 59, 999), 222 "SE Asia Standard Time" => array(-420, 0, -60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 223 "Singapore Standard Time" => array(-480, 0, -60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 224 "South Africa Standard Time" => array(-120, 0, -60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 225 "Sri Lanka Standard Time" => array(-330, 0, -60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 226 //"Syria Standard Time" => array(-120, 0, -60, 0, 10, 4, 5, 23, 59, 59, 999, 0, 4, 4, 1, 23, 59, 59, 999), 227 "Taipei Standard Time" => array(-480, 0, -60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 228 "Tasmania Standard Time" => array(-600, 0, -60, 0, 4, 0, 1, 3, 0, 0, 0, 0, 10, 0, 1, 2, 0, 0, 0), 229 "Tokyo Standard Time" => array(-540, 0, -60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 230 "Tonga Standard Time" => array(-780, 0, -60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 231 //"Ulaanbaatar Standard Time" => array(-480, 0, -60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 232 "US Eastern Standard Time" => array(300, 0, -60, 0, 11, 0, 1, 2, 0, 0, 0, 0, 3, 0, 2, 2, 0, 0, 0), 233 "US Mountain Standard Time" => array(420, 0, -60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 234 //"UTC" => array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 235 //"UTC+12" => array(-720, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 236 //"UTC-02" => array(120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 237 //"UTC-11" => array(660, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 238 "Venezuela Standard Time" => array(270, 0, -60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 239 "Vladivostok Standard Time" => array(-600, 0, -60, 0, 10, 0, 5, 3, 0, 0, 0, 0, 3, 0, 5, 2, 0, 0, 0), 240 "W Australia Standard Time" => array(-480, 0, -60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 241 "W Central Africa Standard Time" => array(-60, 0, -60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 242 "W Europe Standard Time" => array(-60, 0, -60, 0, 10, 0, 5, 3, 0, 0, 0, 0, 3, 0, 5, 2, 0, 0, 0), 243 "West Asia Standard Time" => array(-300, 0, -60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 244 "West Pacific Standard Time" => array(-600, 0, -60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 245 "Yakutsk Standard Time" => array(-540, 0, -60, 0, 10, 0, 5, 3, 0, 0, 0, 0, 3, 0, 5, 2, 0, 0, 0), 246 ); 247 248 /** 249 * Generated list of PHP timezones in GMT timezones 250 * 251 * Created at: 01.06.2012 252 */ 253 private static $phptimezones = array( 254 // -720 min 255 "Dateline Standard Time" => array( 256 "Etc/GMT+12", 257 ), 258 259 // -660 min 260 "Samoa Standard Time" => array( 261 "Etc/GMT+11", 262 "Pacific/Midway", 263 "Pacific/Niue", 264 "Pacific/Pago_Pago", 265 "Pacific/Samoa", 266 "US/Samoa", 267 ), 268 269 // -600 min 270 "Hawaiian Standard Time" => array( 271 "America/Adak", 272 "America/Atka", 273 "Etc/GMT+10", 274 "HST", 275 "Pacific/Honolulu", 276 "Pacific/Johnston", 277 "Pacific/Rarotonga", 278 "Pacific/Tahiti", 279 "US/Aleutian", 280 "US/Hawaii", 281 ), 282 283 // -570 min 284 "-570" => array( 285 "Pacific/Marquesas", 286 ), 287 288 // -540 min 289 "Alaskan Standard Time" => array( 290 "America/Anchorage", 291 "America/Juneau", 292 "America/Nome", 293 "America/Sitka", 294 "America/Yakutat", 295 "Etc/GMT+9", 296 "Pacific/Gambier", 297 "US/Alaska", 298 ), 299 300 // -480 min 301 "Pacific Standard Time" => array( 302 "America/Dawson", 303 "America/Ensenada", 304 "America/Los_Angeles", 305 "America/Metlakatla", 306 "America/Santa_Isabel", 307 "America/Tijuana", 308 "America/Vancouver", 309 "America/Whitehorse", 310 "Canada/Pacific", 311 "Canada/Yukon", 312 "Etc/GMT+8", 313 "Mexico/BajaNorte", 314 "Pacific/Pitcairn", 315 "PST8PDT", 316 "US/Pacific", 317 "US/Pacific-New", 318 ), 319 320 // -420 min 321 "US Mountain Standard Time" => array( 322 "America/Boise", 323 "America/Cambridge_Bay", 324 "America/Chihuahua", 325 "America/Creston", 326 "America/Dawson_Creek", 327 "America/Denver", 328 "America/Edmonton", 329 "America/Hermosillo", 330 "America/Inuvik", 331 "America/Mazatlan", 332 "America/Ojinaga", 333 "America/Phoenix", 334 "America/Shiprock", 335 "America/Yellowknife", 336 "Canada/Mountain", 337 "Etc/GMT+7", 338 "Mexico/BajaSur", 339 "MST", 340 "MST7MDT", 341 "Navajo", 342 "US/Arizona", 343 "US/Mountain", 344 ), 345 346 // -360 min 347 "Central Standard Time" => array( 348 "America/Chicago", 349 "America/Indiana/Knox", 350 "America/Indiana/Tell_City", 351 "America/Knox_IN", 352 "America/North_Dakota/Beulah", 353 "America/North_Dakota/Center", 354 "America/North_Dakota/New_Salem", 355 "America/Rainy_River", 356 "America/Rankin_Inlet", 357 "America/Regina", 358 "America/Resolute", 359 "America/Swift_Current", 360 "America/Tegucigalpa", 361 "America/Winnipeg", 362 "US/Central", 363 "US/Indiana-Starke", 364 "CST6CDT", 365 "Etc/GMT+6", 366 ), 367 "Canada Central Standard Time" => array( 368 "Canada/Central", 369 "Canada/East-Saskatchewan", 370 "Canada/Saskatchewan", 371 ), 372 "Mexico Standard Time" => array( 373 "America/Mexico_City", 374 "America/Monterrey", 375 "Mexico/General", 376 ), 377 "Central America Standard Time" => array( 378 "America/Bahia_Banderas", 379 "America/Belize", 380 "America/Cancun", 381 "America/Costa_Rica", 382 "America/El_Salvador", 383 "America/Guatemala", 384 "America/Managua", 385 "America/Matamoros", 386 "America/Menominee", 387 "America/Merida", 388 "Chile/EasterIsland", 389 "Pacific/Easter", 390 "Pacific/Galapagos", 391 ), 392 393 // -300 min 394 "US Eastern Standard Time" => array( 395 "America/Detroit", 396 "America/Fort_Wayne", 397 "America/Grand_Turk", 398 "America/Indiana/Indianapolis", 399 "America/Indiana/Marengo", 400 "America/Indiana/Petersburg", 401 "America/Indiana/Vevay", 402 "America/Indiana/Vincennes", 403 "America/Indiana/Winamac", 404 "America/Indianapolis", 405 "America/Jamaica", 406 "America/Kentucky/Louisville", 407 "America/Kentucky/Monticello", 408 "America/Louisville", 409 "America/Montreal", 410 "America/New_York", 411 "America/Thunder_Bay", 412 "America/Toronto", 413 "Canada/Eastern", 414 "Cuba", 415 "EST", 416 "EST5EDT", 417 "Etc/GMT+5", 418 "Jamaica", 419 "US/East-Indiana", 420 "US/Eastern", 421 "US/Michigan", 422 ), 423 "SA Pacific Standard Time" => array( 424 "America/Atikokan", 425 "America/Bogota", 426 "America/Cayman", 427 "America/Coral_Harbour", 428 "America/Guayaquil", 429 "America/Havana", 430 "America/Iqaluit", 431 "America/Lima", 432 "America/Nassau", 433 "America/Nipigon", 434 "America/Panama", 435 "America/Pangnirtung", 436 "America/Port-au-Prince", 437 ), 438 439 // -270 min 440 "Venezuela Standard Time" => array( 441 "America/Caracas", 442 ), 443 // -240 min 444 "Atlantic Standard Time" => array( 445 "America/Barbados", 446 "America/Blanc-Sablon", 447 "America/Glace_Bay", 448 "America/Goose_Bay", 449 "America/Halifax", 450 "America/Lower_Princes", 451 "America/St_Barthelemy", 452 "America/St_Kitts", 453 "America/St_Lucia", 454 "America/St_Thomas", 455 "America/St_Vincent", 456 "America/Thule", 457 "America/Tortola", 458 "America/Virgin", 459 "Atlantic/Bermuda", 460 "Canada/Atlantic", 461 "Etc/GMT+4", 462 ), 463 "SA Western Standard Time" => array( 464 "America/Anguilla", 465 "America/Antigua", 466 "America/Aruba", 467 "America/Asuncion", 468 "America/Boa_Vista", 469 "America/Campo_Grande", 470 "America/Cuiaba", 471 "America/Curacao", 472 "America/Dominica", 473 "America/Eirunepe", 474 "America/Grenada", 475 "America/Guadeloupe", 476 "America/Guyana", 477 "America/Kralendijk", 478 "America/La_Paz", 479 "America/Manaus", 480 "America/Marigot", 481 "America/Martinique", 482 "America/Moncton", 483 "America/Montserrat", 484 "America/Port_of_Spain", 485 "America/Porto_Acre", 486 "America/Porto_Velho", 487 "America/Puerto_Rico", 488 "America/Rio_Branco", 489 "Brazil/Acre", 490 "Brazil/West", 491 ), 492 "Pacific SA Standard Time" => array( 493 "America/Santiago", 494 "America/Santo_Domingo", 495 "Antarctica/Palmer", 496 "Chile/Continental", 497 ), 498 499 // -210 min 500 "Newfoundland and Labrador Standard Time" => array( 501 "America/St_Johns", 502 "Canada/Newfoundland", 503 ), 504 505 // -180 min 506 "E South America Standard Time" => array( 507 "America/Araguaina", 508 "America/Bahia", 509 "America/Belem", 510 "America/Fortaleza", 511 "America/Maceio", 512 "America/Recife", 513 "America/Sao_Paulo", 514 "Brazil/East", 515 "Etc/GMT+3", 516 ), 517 "SA Eastern Standard Time" => array( 518 "America/Argentina/Buenos_Aires", 519 "America/Argentina/Catamarca", 520 "America/Argentina/ComodRivadavia", 521 "America/Argentina/Cordoba", 522 "America/Argentina/Jujuy", 523 "America/Argentina/La_Rioja", 524 "America/Argentina/Mendoza", 525 "America/Argentina/Rio_Gallegos", 526 "America/Argentina/Salta", 527 "America/Argentina/San_Juan", 528 "America/Argentina/San_Luis", 529 "America/Argentina/Tucuman", 530 "America/Argentina/Ushuaia", 531 "America/Buenos_Aires", 532 "America/Catamarca", 533 "America/Cayenne", 534 "America/Cordoba", 535 "America/Godthab", 536 "America/Jujuy", 537 "America/Mendoza", 538 "America/Miquelon", 539 "America/Montevideo", 540 "America/Paramaribo", 541 "America/Rosario", 542 "America/Santarem", 543 ), 544 "Greenland Standard Time" => array( 545 "Antarctica/Rothera", 546 "Atlantic/Stanley", 547 ), 548 549 // -120 min 550 "Mid-Atlantic Standard Time" => array( 551 "America/Noronha", 552 "Atlantic/South_Georgia", 553 "Brazil/DeNoronha", 554 "Etc/GMT+2", 555 ), 556 557 // -60 min 558 "Azores Standard Time" => array( 559 "Atlantic/Azores", 560 "Etc/GMT+1", 561 ), 562 "Cape Verde Standard Time" => array( 563 "America/Scoresbysund", 564 "Atlantic/Cape_Verde", 565 ), 566 567 // 0 min 568 "GMT Standard Time" => array( 569 "Eire", 570 "Etc/GMT", 571 "Etc/GMT+0", 572 "Etc/GMT-0", 573 "Etc/GMT0", 574 "Etc/Greenwich", 575 "Etc/UCT", 576 "Etc/Universal", 577 "Etc/UTC", 578 "Etc/Zulu", 579 "Europe/Belfast", 580 "Europe/Dublin", 581 "Europe/Guernsey", 582 "Europe/Isle_of_Man", 583 "Europe/Jersey", 584 "Europe/Lisbon", 585 "Europe/London", 586 "Factory", 587 "GB", 588 "GB-Eire", 589 "GMT", 590 "GMT+0", 591 "GMT-0", 592 "GMT0", 593 "Greenwich", 594 "Iceland", 595 "Portugal", 596 "UCT", 597 "Universal", 598 "UTC", 599 ), 600 "Greenwich Standard Time" => array( 601 "Africa/Abidjan", 602 "Africa/Accra", 603 "Africa/Bamako", 604 "Africa/Banjul", 605 "Africa/Bissau", 606 "Africa/Casablanca", 607 "Africa/Conakry", 608 "Africa/Dakar", 609 "Africa/El_Aaiun", 610 "Africa/Freetown", 611 "Africa/Lome", 612 "Africa/Monrovia", 613 "Africa/Nouakchott", 614 "Africa/Ouagadougou", 615 "Africa/Sao_Tome", 616 "Africa/Timbuktu", 617 "America/Danmarkshavn", 618 "Atlantic/Canary", 619 "Atlantic/Faeroe", 620 "Atlantic/Faroe", 621 "Atlantic/Madeira", 622 "Atlantic/Reykjavik", 623 "Atlantic/St_Helena", 624 "Zulu", 625 ), 626 627 // +60 min 628 "Central Europe Standard Time" => array( 629 "Europe/Belgrade", 630 "Europe/Bratislava", 631 "Europe/Budapest", 632 "Europe/Ljubljana", 633 "Europe/Prague", 634 "Europe/Vaduz", 635 ), 636 "Central European Standard Time" => array( 637 "Europe/Sarajevo", 638 "Europe/Skopje", 639 "Europe/Warsaw", 640 "Europe/Zagreb", 641 "MET", 642 "Poland", 643 ), 644 "Romance Standard Time" => array( 645 "Europe/Andorra", 646 "Europe/Brussels", 647 "Europe/Copenhagen", 648 "Europe/Gibraltar", 649 "Europe/Madrid", 650 "Europe/Malta", 651 "Europe/Monaco", 652 "Europe/Paris", 653 "Europe/Podgorica", 654 "Europe/San_Marino", 655 "Europe/Tirane", 656 ), 657 "W Europe Standard Time" => array( 658 "Europe/Amsterdam", 659 "Europe/Berlin", 660 "Europe/Luxembourg", 661 "Europe/Vatican", 662 "Europe/Rome", 663 "Europe/Stockholm", 664 "Arctic/Longyearbyen", 665 "Europe/Vienna", 666 "Europe/Zurich", 667 "Europe/Oslo", 668 "WET", 669 "CET", 670 "Etc/GMT-1", 671 ), 672 "W Central Africa Standard Time" => array( 673 "Africa/Algiers", 674 "Africa/Bangui", 675 "Africa/Brazzaville", 676 "Africa/Ceuta", 677 "Africa/Douala", 678 "Africa/Kinshasa", 679 "Africa/Lagos", 680 "Africa/Libreville", 681 "Africa/Luanda", 682 "Africa/Malabo", 683 "Africa/Ndjamena", 684 "Africa/Niamey", 685 "Africa/Porto-Novo", 686 "Africa/Tunis", 687 "Africa/Windhoek", 688 "Atlantic/Jan_Mayen", 689 ), 690 691 // +120 min 692 "E Europe Standard Time" => array( 693 "Europe/Bucharest", 694 "EET", 695 "Etc/GMT-2", 696 "Europe/Chisinau", 697 "Europe/Mariehamn", 698 "Europe/Nicosia", 699 "Europe/Simferopol", 700 "Europe/Tiraspol", 701 "Europe/Uzhgorod", 702 "Europe/Zaporozhye", 703 ), 704 "Egypt Standard Time" => array( 705 "Africa/Cairo", 706 "Africa/Tripoli", 707 "Egypt", 708 "Libya", 709 ), 710 "FLE Standard Time" => array( 711 "Europe/Helsinki", 712 "Europe/Kiev", 713 "Europe/Riga", 714 "Europe/Sofia", 715 "Europe/Tallinn", 716 "Europe/Vilnius", 717 ), 718 "GTB Standard Time" => array( 719 "Asia/Istanbul", 720 "Europe/Athens", 721 "Europe/Istanbul", 722 "Turkey", 723 ), 724 "Israel Standard Time" => array( 725 "Asia/Amman", 726 "Asia/Beirut", 727 "Asia/Damascus", 728 "Asia/Gaza", 729 "Asia/Hebron", 730 "Asia/Nicosia", 731 "Asia/Tel_Aviv", 732 "Asia/Jerusalem", 733 "Israel", 734 ), 735 "South Africa Standard Time" => array( 736 "Africa/Blantyre", 737 "Africa/Bujumbura", 738 "Africa/Gaborone", 739 "Africa/Harare", 740 "Africa/Johannesburg", 741 "Africa/Kigali", 742 "Africa/Lubumbashi", 743 "Africa/Lusaka", 744 "Africa/Maputo", 745 "Africa/Maseru", 746 "Africa/Mbabane", 747 ), 748 749 // +180 min 750 "Russian Standard Time" => array( 751 "Antarctica/Syowa", 752 "Europe/Kaliningrad", 753 "Europe/Minsk", 754 "Etc/GMT-3", 755 ), 756 "Arab Standard Time" => array( 757 "Asia/Qatar", 758 "Asia/Kuwait", 759 "Asia/Riyadh", 760 ), 761 "E Africa Standard Time" => array( 762 "Africa/Addis_Ababa", 763 "Africa/Asmara", 764 "Africa/Asmera", 765 "Africa/Dar_es_Salaam", 766 "Africa/Djibouti", 767 "Africa/Juba", 768 "Africa/Kampala", 769 "Africa/Khartoum", 770 "Africa/Mogadishu", 771 "Africa/Nairobi", 772 ), 773 "Arabic Standard Time" => array( 774 "Asia/Aden", 775 "Asia/Baghdad", 776 "Asia/Bahrain", 777 "Indian/Antananarivo", 778 "Indian/Comoro", 779 "Indian/Mayotte", 780 ), 781 782 // +210 min 783 "Iran Standard Time" => array( 784 "Asia/Tehran", 785 "Iran", 786 ), 787 788 // +240 min 789 "Arabian Standard Time" => array( 790 "Asia/Dubai", 791 "Asia/Muscat", 792 "Indian/Mahe", 793 "Indian/Mauritius", 794 "Indian/Reunion", 795 ), 796 "Caucasus Standard Time" => array( 797 "Asia/Baku", 798 "Asia/Tbilisi", 799 "Asia/Yerevan", 800 "Etc/GMT-4", 801 "Europe/Moscow", 802 "Europe/Samara", 803 "Europe/Volgograd", 804 "W-SU", 805 ), 806 807 // +270 min 808 "Transitional Islamic State of Afghanistan Standard Time" => array( 809 "Asia/Kabul", 810 ), 811 812 // +300 min 813 "Ekaterinburg Standard Time" => array( 814 "Antarctica/Mawson", 815 ), 816 "West Asia Standard Time" => array( 817 "Asia/Aqtau", 818 "Asia/Aqtobe", 819 "Asia/Ashgabat", 820 "Asia/Ashkhabad", 821 "Asia/Dushanbe", 822 "Asia/Karachi", 823 "Asia/Oral", 824 "Asia/Samarkand", 825 "Asia/Tashkent", 826 "Etc/GMT-5", 827 "Indian/Kerguelen", 828 "Indian/Maldives", 829 ), 830 831 // +330 min 832 "India Standard Time" => array( 833 "Asia/Calcutta", 834 "Asia/Colombo", 835 "Asia/Kolkata", 836 ), 837 838 // +345 min 839 "Nepal Standard Time" => array( 840 "Asia/Kathmandu", 841 "Asia/Katmandu", 842 ), 843 844 // +360 min 845 "Central Asia Standard Time" => array( 846 "Asia/Dacca", 847 "Asia/Dhaka", 848 ), 849 "Sri Lanka Standard Time" => array( 850 "Indian/Chagos", 851 ), 852 "N Central Asia Standard Time" => array( 853 "Antarctica/Vostok", 854 "Asia/Almaty", 855 "Asia/Bishkek", 856 "Asia/Qyzylorda", 857 "Asia/Thimbu", 858 "Asia/Thimphu", 859 "Asia/Yekaterinburg", 860 "Etc/GMT-6", 861 ), 862 863 // +390 min 864 "Myanmar Standard Time" => array( 865 "Asia/Rangoon", 866 "Indian/Cocos", 867 ), 868 869 // +420 min 870 "SE Asia Standard Time" => array( 871 "Asia/Bangkok", 872 "Asia/Ho_Chi_Minh", 873 "Asia/Hovd", 874 "Asia/Jakarta", 875 "Asia/Phnom_Penh", 876 "Asia/Saigon", 877 "Indian/Christmas", 878 ), 879 "North Asia Standard Time" => array( 880 "Antarctica/Davis", 881 "Asia/Novokuznetsk", 882 "Asia/Novosibirsk", 883 "Asia/Omsk", 884 "Asia/Pontianak", 885 "Asia/Vientiane", 886 "Etc/GMT-7", 887 ), 888 889 // +480 min 890 "China Standard Time" => array( 891 "Asia/Brunei", 892 "Asia/Choibalsan", 893 "Asia/Chongqing", 894 "Asia/Chungking", 895 "Asia/Harbin", 896 "Asia/Hong_Kong", 897 "Asia/Shanghai", 898 "Asia/Ujung_Pandang", 899 "Asia/Urumqi", 900 "Hongkong", 901 "PRC", 902 "ROC", 903 ), 904 "Singapore Standard Time" => array( 905 "Singapore", 906 "Asia/Singapore", 907 "Asia/Kuala_Lumpur", 908 ), 909 "Taipei Standard Time" => array( 910 "Asia/Taipei", 911 ), 912 "W Australia Standard Time" => array( 913 "Australia/Perth", 914 "Australia/West", 915 ), 916 "North Asia East Standard Time" => array( 917 "Antarctica/Casey", 918 "Asia/Kashgar", 919 "Asia/Krasnoyarsk", 920 "Asia/Kuching", 921 "Asia/Macao", 922 "Asia/Macau", 923 "Asia/Makassar", 924 "Asia/Manila", 925 "Etc/GMT-8", 926 "Asia/Ulaanbaatar", 927 "Asia/Ulan_Bator", 928 ), 929 930 // +525 min 931 "525" => array( 932 "Australia/Eucla", 933 ), 934 935 // +540 min 936 "Korea Standard Time" => array( 937 "Asia/Seoul", 938 "Asia/Pyongyang", 939 "ROK", 940 ), 941 "Tokyo Standard Time" => array( 942 "Asia/Tokyo", 943 "Japan", 944 "Etc/GMT-9", 945 ), 946 "Yakutsk Standard Time" => array( 947 "Asia/Dili", 948 "Asia/Irkutsk", 949 "Asia/Jayapura", 950 "Pacific/Palau", 951 ), 952 953 // +570 min 954 "AUS Central Standard Time" => array( 955 "Australia/Darwin", 956 "Australia/North", 957 ), 958 // DST 959 "Cen Australia Standard Time" => array( 960 "Australia/Adelaide", 961 "Australia/Broken_Hill", 962 "Australia/South", 963 "Australia/Yancowinna", 964 ), 965 966 // +600 min 967 "AUS Eastern Standard Time" => array( 968 "Australia/Canberra", 969 "Australia/Melbourne", 970 "Australia/Sydney", 971 "Australia/Currie", 972 "Australia/ACT", 973 "Australia/NSW", 974 "Australia/Victoria", 975 ), 976 "E Australia Standard Time" => array( 977 "Etc/GMT-10", 978 "Australia/Brisbane", 979 "Australia/Queensland", 980 "Australia/Lindeman", 981 ), 982 "Tasmania Standard Time" => array( 983 "Australia/Hobart", 984 "Australia/Tasmania", 985 ), 986 "Vladivostok Standard Time" => array( 987 "Antarctica/DumontDUrville", 988 ), 989 "West Pacific Standard Time" => array( 990 "Asia/Yakutsk", 991 "Pacific/Chuuk", 992 "Pacific/Guam", 993 "Pacific/Port_Moresby", 994 "Pacific/Saipan", 995 "Pacific/Truk", 996 "Pacific/Yap", 997 ), 998 999 // +630 min 1000 "630" => array( 1001 "Australia/LHI", 1002 "Australia/Lord_Howe", 1003 ), 1004 1005 // +660 min 1006 "Central Pacific Standard Time" => array( 1007 "Antarctica/Macquarie", 1008 "Asia/Sakhalin", 1009 "Asia/Vladivostok", 1010 "Etc/GMT-11", 1011 "Pacific/Efate", 1012 "Pacific/Guadalcanal", 1013 "Pacific/Kosrae", 1014 "Pacific/Noumea", 1015 "Pacific/Pohnpei", 1016 "Pacific/Ponape", 1017 ), 1018 1019 // 690 min 1020 "690" => array( 1021 "Pacific/Norfolk", 1022 ), 1023 1024 // +720 min 1025 "Fiji Islands Standard Time" => array( 1026 "Asia/Anadyr", 1027 "Asia/Kamchatka", 1028 "Asia/Magadan", 1029 "Kwajalein", 1030 ), 1031 "New Zealand Standard Time" => array( 1032 "Antarctica/McMurdo", 1033 "Antarctica/South_Pole", 1034 "Etc/GMT-12", 1035 "NZ", 1036 "Pacific/Auckland", 1037 "Pacific/Fiji", 1038 "Pacific/Funafuti", 1039 "Pacific/Kwajalein", 1040 "Pacific/Majuro", 1041 "Pacific/Nauru", 1042 "Pacific/Tarawa", 1043 "Pacific/Wake", 1044 "Pacific/Wallis", 1045 ), 1046 1047 // +765 min 1048 "765" => array( 1049 "NZ-CHAT", 1050 "Pacific/Chatham", 1051 ), 1052 1053 // +780 min 1054 "Tonga Standard Time" => array( 1055 "Etc/GMT-13", 1056 "Pacific/Apia", 1057 "Pacific/Enderbury", 1058 "Pacific/Tongatapu", 1059 ), 1060 1061 // +840 min 1062 "840" => array( 1063 "Etc/GMT-14", 1064 "Pacific/Fakaofo", 1065 "Pacific/Kiritimati", 1066 ), 1067 ); 1068 1069 /** 1070 * Returns a full timezone array 1071 * 1072 * @param string $phptimezone (opt) a php timezone string. 1073 * If omitted the env. default timezone is used. 1074 * 1075 * @access public 1076 * @return array 1077 */ 1078 static public function GetFullTZ($phptimezone = false) { 1079 if ($phptimezone === false) 1080 $phptimezone = date_default_timezone_get(); 1081 1082 ZLog::Write(LOGLEVEL_DEBUG, "TimezoneUtil::GetFullTZ() for ". $phptimezone); 1083 1084 $servertzname = self::guessTZNameFromPHPName($phptimezone); 1085 return self::GetFullTZFromTZName($servertzname); 1086 } 1087 1088 /** 1089 * Returns a full timezone array 1090 * 1091 * @param string $tzname a TZID value 1092 * 1093 * @access public 1094 * @return array 1095 */ 1096 static public function GetFullTZFromTZName($tzname) { 1097 if (!array_key_exists($tzname, self::$tzonesoffsets)) { 1098 ZLog::Write(LOGLEVEL_DEBUG, sprintf("TimezoneUtil::GetFullTZFromTZName('%s'): Is a PHP TimeZone, converting", $tzname)); 1099 $tzname = self::guessTZNameFromPHPName($tzname); 1100 } 1101 1102 $offset = self::$tzonesoffsets[$tzname]; 1103 1104 $tz = array( 1105 "bias" => $offset[0], 1106 "tzname" => self::encodeTZName(self::getMSTZnameFromTZName($tzname)), 1107 "dstendyear" => $offset[3], 1108 "dstendmonth" => $offset[4], 1109 "dstendday" => $offset[5], 1110 "dstendweek" => $offset[6], 1111 "dstendhour" => $offset[7], 1112 "dstendminute" => $offset[8], 1113 "dstendsecond" => $offset[9], 1114 "dstendmillis" => $offset[10], 1115 "stdbias" => $offset[1], 1116 "tznamedst" => self::encodeTZName(self::getMSTZnameFromTZName($tzname)), 1117 "dststartyear" => $offset[11], 1118 "dststartmonth" => $offset[12], 1119 "dststartday" => $offset[13], 1120 "dststartweek" => $offset[14], 1121 "dststarthour" => $offset[15], 1122 "dststartminute" => $offset[16], 1123 "dststartsecond" => $offset[17], 1124 "dststartmillis" => $offset[18], 1125 "dstbias" => $offset[2] 1126 ); 1127 1128 return $tz; 1129 } 1130 1131 /** 1132 * Sets the timezone name by matching data from the offset (bias etc) 1133 * 1134 * @param array $offset a z-push timezone array 1135 * 1136 * @access public 1137 * @return array 1138 */ 1139 static public function FillTZNames($tz) { 1140 ZLog::Write(LOGLEVEL_DEBUG, "TimezoneUtil::FillTZNames() filling up bias ". $tz["bias"]); 1141 if (!isset($tz["bias"])) 1142 ZLog::Write(LOGLEVEL_WARN, "TimezoneUtil::FillTZNames() submitted TZ array does not have a bias"); 1143 else { 1144 $tzname = self::guessTZNameFromOffset($tz); 1145 $tz['tzname'] = $tz['tznamedst'] = self::encodeTZName(self::getMSTZnameFromTZName($tzname)); 1146 } 1147 return $tz; 1148 } 1149 1150 /** 1151 * Tries to find a timezone using the Bias and other offset parameters 1152 * 1153 * @param array $offset a z-push timezone array 1154 * 1155 * @access public 1156 * @return string 1157 */ 1158 static private function guessTZNameFromOffset($offset) { 1159 // try to find a quite exact match 1160 foreach (self::$tzonesoffsets as $tzname => $tzoffset) { 1161 if ($offset["bias"] == $tzoffset[0] && 1162 isset($offset["dstendmonth"]) && $offset["dstendmonth"] == $tzoffset[4] && 1163 isset($offset["dstendday"]) && $offset["dstendday"] == $tzoffset[6] && 1164 isset($offset["dststartmonth"]) && $offset["dststartmonth"] == $tzoffset[12] && 1165 isset($offset["dststartday"]) && $offset["dststartday"] == $tzoffset[14]) 1166 return $tzname; 1167 } 1168 1169 // try to find a bias match 1170 foreach (self::$tzonesoffsets as $tzname => $tzoffset) { 1171 if ($offset["bias"] == $tzoffset[0]) 1172 return $tzname; 1173 } 1174 1175 // nothing found? return gmt 1176 ZLog::Write(LOGLEVEL_WARN, "TimezoneUtil::guessTZNameFromOffset() no timezone found for the data submitted. Returning 'GMT Standard Time'."); 1177 return "GMT Standard Time"; 1178 } 1179 1180 /** 1181 * Tries to find a AS timezone for a php timezone. 1182 * 1183 * @param string $phpname a php timezone name 1184 * 1185 * @access public 1186 * @return string 1187 */ 1188 static private function guessTZNameFromPHPName($phpname) { 1189 foreach (self::$phptimezones as $tzn => $phptzs) { 1190 if (in_array($phpname, $phptzs)) { 1191 if (!is_int($tzn)) { 1192 return $tzn; 1193 } 1194 break; 1195 } 1196 } 1197 ZLog::Write(LOGLEVEL_ERROR, sprintf("TimezoneUtil::guessTZNameFromPHPName() no compatible timezone found for '%s'. Returning 'GMT Standard Time'. Please contact the Z-Push dev team.", $phpname)); 1198 return self::$mstzones["085"][0]; 1199 } 1200 1201 /** 1202 * Returns an AS compatible tz name 1203 * 1204 * @param string $name internal timezone name 1205 * 1206 * @access private 1207 * @return string 1208 */ 1209 static private function getMSTZnameFromTZName($name) { 1210 // if $name is empty, get the timezone from system 1211 if (trim($name) == '') { 1212 $name = date_default_timezone_get(); 1213 ZLog::Write(LOGLEVEL_INFO, sprintf("TimezoneUtil::getMSTZnameFromTZName(): empty timezone name sent. Got timezone from the system: '%s'", $name)); 1214 } 1215 1216 foreach (self::$mstzones as $mskey => $msdefs) { 1217 if ($name == $msdefs[0]) 1218 return $msdefs[1]; 1219 } 1220 1221 // Not found? Then retrieve the correct TZName first and try again. 1222 // That's ugly and needs a proper fix. But for now this method can convert 1223 // - Europe/Berlin 1224 // - W Europe Standard Time 1225 // to "(GMT+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna" 1226 // which is more correct than the hardcoded default of (GMT+00:00...) 1227 $tzName = ''; 1228 foreach (self::$phptimezones as $tzn => $phptzs) { 1229 if (in_array($name, $phptzs)) { 1230 $tzName = $tzn; 1231 break; 1232 } 1233 } 1234 if ($tzName != '') { 1235 foreach (self::$mstzones as $mskey => $msdefs) { 1236 if ($tzName == $msdefs[0]) 1237 return $msdefs[1]; 1238 } 1239 } 1240 1241 ZLog::Write(LOGLEVEL_WARN, sprintf("TimezoneUtil::getMSTZnameFromTZName() no MS name found for '%s'. Returning '(GMT) Greenwich Mean Time: Dublin, Edinburgh, Lisbon, London'", $name)); 1242 return self::$mstzones["085"][1]; 1243 } 1244 1245 /** 1246 * Encodes the tz name to UTF-16 compatible with a syncblob 1247 * 1248 * @param string $name timezone name 1249 * 1250 * @access public 1251 * @return string 1252 */ 1253 static private function encodeTZName($name) { 1254 return substr(iconv('UTF-8', 'UTF-16', $name),2,-1); 1255 } 1256 1257 /** 1258 * Test to check if $mstzones and $tzonesoffsets can be resolved 1259 * in both directions. 1260 * 1261 * @access public 1262 * @return 1263 */ 1264 static public function TZtest() { 1265 foreach (self::$mstzones as $mskey => $msdefs) { 1266 if (!array_key_exists($msdefs[0], self::$tzonesoffsets)) 1267 echo "key '". $msdefs[0]. "' not found in tzonesoffsets\n"; 1268 } 1269 1270 foreach (self::$tzonesoffsets as $tzname => $offset) { 1271 $found = false; 1272 foreach (self::$mstzones as $mskey => $msdefs) { 1273 if ($tzname == $msdefs[0]) { 1274 $found = true; 1275 break; 1276 } 1277 } 1278 if (!$found) 1279 echo "key '$tzname' NOT FOUND\n"; 1280 } 1281 } 1282 1283 /** 1284 * Pack timezone info for Sync. 1285 * 1286 * @param array $tz 1287 * 1288 * @access public 1289 * @return string 1290 */ 1291 static public function GetSyncBlobFromTZ($tz) { 1292 // set the correct TZ name (done using the Bias) 1293 if (!isset($tz["tzname"]) || !$tz["tzname"] || !isset($tz["tznamedst"]) || !$tz["tznamedst"]) 1294 $tz = TimezoneUtil::FillTZNames($tz); 1295 1296 $packed = pack("la64vvvvvvvv" . "la64vvvvvvvv" . "l", 1297 $tz["bias"], $tz["tzname"], 0, $tz["dstendmonth"], $tz["dstendday"], $tz["dstendweek"], $tz["dstendhour"], $tz["dstendminute"], $tz["dstendsecond"], $tz["dstendmillis"], 1298 $tz["stdbias"], $tz["tznamedst"], 0, $tz["dststartmonth"], $tz["dststartday"], $tz["dststartweek"], $tz["dststarthour"], $tz["dststartminute"], $tz["dststartsecond"], $tz["dststartmillis"], 1299 $tz["dstbias"]); 1300 1301 return $packed; 1302 } 1303 1304 /** 1305 * Generate date object from string and timezone. 1306 * 1307 * @param string $value 1308 * @param string $timezone 1309 * 1310 * @access public 1311 * @return int epoch 1312 */ 1313 public static function MakeUTCDate($value, $timezone = null) { 1314 $tz = null; 1315 if ($timezone) { 1316 $tz = timezone_open($timezone); 1317 } 1318 if (!$tz) { 1319 //If there is no timezone set, we use the default timezone 1320 $tz = timezone_open(date_default_timezone_get()); 1321 } 1322 //20110930T090000Z 1323 $date = date_create_from_format('Ymd\THis\Z', $value, timezone_open("UTC")); 1324 if (!$date) { 1325 //20110930T090000 1326 $date = date_create_from_format('Ymd\THis', $value, $tz); 1327 } 1328 if (!$date) { 1329 //20110930 (Append T000000Z to the date, so it starts at midnight) 1330 $date = date_create_from_format('Ymd\THis\Z', $value . "T000000Z", $tz); 1331 } 1332 return date_timestamp_get($date); 1333 } 1334 1335 1336 /** 1337 * Generate a tzid from various formats 1338 * 1339 * @param str $timezone 1340 * 1341 * @access public 1342 * @return timezone id 1343 */ 1344 public static function ParseTimezone($timezone) { 1345 //(GMT+01.00) Amsterdam / Berlin / Bern / Rome / Stockholm / Vienna 1346 if (preg_match('/GMT(\\+|\\-)0(\d)/', $timezone, $matches)) { 1347 return "Etc/GMT" . $matches[1] . $matches[2]; 1348 } 1349 //(GMT+10.00) XXX / XXX / XXX / XXX 1350 if (preg_match('/GMT(\\+|\\-)1(\d)/', $timezone, $matches)) { 1351 return "Etc/GMT" . $matches[1] . "1" . $matches[2]; 1352 } 1353 ///inverse.ca/20101018_1/Europe/Amsterdam or /inverse.ca/20101018_1/America/Argentina/Buenos_Aires 1354 if (preg_match('/\/[.[:word:]]+\/\w+\/(\w+)\/([\w\/]+)/', $timezone, $matches)) { 1355 return $matches[1] . "/" . $matches[2]; 1356 } 1357 return self::getMSTZnameFromTZName(trim($timezone, '"')); 1358 } 1359 1360 /** 1361 * Returns a timezone supported by PHP for DateTimeZone constructor. 1362 * @see http://php.net/manual/en/timezones.php 1363 * 1364 * @param string $timezone 1365 * 1366 * @access public 1367 * @return string 1368 */ 1369 public static function GetPhpSupportedTimezone($timezone) { 1370 if (in_array($timezone, DateTimeZone::listIdentifiers())) { 1371 ZLog::Write(LOGLEVEL_DEBUG, sprintf("TimezoneUtil::GetPhpSupportedTimezone(): '%s' is a PHP supported timezone", $timezone)); 1372 return $timezone; 1373 } 1374 $dtz = date_default_timezone_get(); 1375 ZLog::Write(LOGLEVEL_DEBUG, sprintf("TimezoneUtil::GetPhpSupportedTimezone(): '%s' is not a PHP supported timezone. Returning default timezone: '%s'", $timezone, $dtz)); 1376 return $dtz; 1377 } 1378 1379 /** 1380 * Returns official timezone name from windows timezone name. 1381 * E.g. "W Europe Standard Time" for "(GMT+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna". 1382 * 1383 * @param string $winTz Timezone name in windows 1384 * 1385 * @access public 1386 * @return string timezone name 1387 */ 1388 public static function GetTZNameFromWinTZ($winTz = false) { 1389 1390 // Return "GMT Standard Time" per default 1391 if ($winTz === false) { 1392 return self::$mstzones['085'][0]; 1393 } 1394 1395 foreach (self::$mstzones as $mskey => $msdefs) { 1396 if ($winTz == $msdefs[1]) { 1397 return $msdefs[0]; 1398 } 1399 } 1400 return self::$mstzones['085'][0]; 1401 } 1402} 1403