001 package railo.commons.date; 002 003 import java.util.Calendar; 004 import java.util.HashMap; 005 import java.util.Map; 006 import java.util.TimeZone; 007 008 import railo.commons.lang.StringUtil; 009 import railo.runtime.engine.ThreadLocalPageContext; 010 import railo.runtime.exp.ExpressionException; 011 import railo.runtime.op.Caster; 012 import railo.runtime.type.util.ListUtil; 013 014 public class TimeZoneUtil { 015 016 private static final Map<String,TimeZone> IDS=new HashMap<String,TimeZone>(); 017 018 static { 019 String[] ids=TimeZone.getAvailableIDs(); 020 for(int i=0;i<ids.length;i++){ 021 IDS.put(ids[i].toLowerCase(), TimeZone.getTimeZone(ids[i])); 022 } 023 TimeZone def = TimeZone.getDefault(); 024 if(def!=null)IDS.put(def.getID(),def); 025 IDS.put("jvm", TimeZone.getDefault()); 026 IDS.put("default", TimeZone.getDefault()); 027 IDS.put("", TimeZone.getDefault()); 028 029 // MS specific Timezone definions 030 set("Dateline Standard Time",TimeZoneConstants.ETC_GMT_PLUS_12); // (GMT-12:00) International Date Line West 031 set("Samoa Standard Time",TimeZoneConstants.PACIFIC_MIDWAY); // (GMT-11:00) Midway Island, Samoa 032 set("Hawaiian Standard Time",TimeZoneConstants.HST); // (GMT-10:00) Hawaii 033 set("Alaskan Standard Time",TimeZoneConstants.AST); // (GMT-09:00) Alaska 034 set("Pacific Standard Time",TimeZoneConstants.PST); // (GMT-08:00) Pacific Time (US and Canada); Tijuana 035 set("Mountain Standard Time",TimeZoneConstants.MST); // (GMT-07:00) Mountain Time (US and Canada) 036 set("Mexico Standard Time",TimeZoneConstants.MEXICO_GENERAL); // (GMT-06:00) Guadalajara, Mexico City, Monterrey 037 set("Mexico Standard Time 2",TimeZoneConstants.AMERICA_CHIHUAHUA); // (GMT-07:00) Chihuahua, La Paz, Mazatlan 038 set("U.S. Mountain Standard Time",TimeZoneConstants.MST); // (GMT-07:00) Arizona 039 set("Central Standard Time",TimeZoneConstants.CST); // (GMT-06:00) Central Time (US and Canada 040 set("Canada Central Standard Time",TimeZoneConstants.CANADA_CENTRAL); // (GMT-06:00) Saskatchewan 041 set("Central America Standard Time",TimeZoneConstants.CST); // (GMT-06:00) Central America 042 set("Eastern Standard Time",TimeZoneConstants.EST); // (GMT-05:00) Eastern Time (US and Canada) 043 set("U.S. Eastern Standard Time",TimeZoneConstants.EST); // (GMT-05:00) Indiana (East) 044 set("S.A. Pacific Standard Time",TimeZoneConstants.AMERICA_BOGOTA); // (GMT-05:00) Bogota, Lima, Quito 045 set("Atlantic Standard Time",TimeZoneConstants.CANADA_ATLANTIC); // (GMT-04:00) Atlantic Time (Canada) 046 set("S.A. Western Standard Time",TimeZoneConstants.AMERICA_ANTIGUA); // (GMT-04:00) Caracas, La Paz 047 set("Pacific S.A. Standard Time",TimeZoneConstants.AMERICA_SANTIAGO); // (GMT-04:00) Santiago 048 set("Newfoundland and Labrador Standard Time",TimeZoneConstants.CNT); // (GMT-03:30) Newfoundland and Labrador 049 set("E. South America Standard Time",TimeZoneConstants.BET); // (GMT-03:00) Brasilia 050 set("S.A. Eastern Standard Time",TimeZoneConstants.AMERICA_ARGENTINA_BUENOS_AIRES); // (GMT-03:00) Buenos Aires, Georgetown 051 set("Greenland Standard Time",TimeZoneConstants.AMERICA_GODTHAB); // (GMT-03:00) Greenland 052 set("Mid-Atlantic Standard Time",TimeZoneConstants.AMERICA_NORONHA); // (GMT-02:00) Mid-Atlantic 053 set("Azores Standard Time",TimeZoneConstants.ATLANTIC_AZORES); // (GMT-01:00) Azores 054 set("Cape Verde Standard Time",TimeZoneConstants.ATLANTIC_CAPE_VERDE); // (GMT-01:00) Cape Verde Islands 055 set("Central Europe Standard Time",TimeZoneConstants.CET); // (GMT+01:00) Belgrade, Bratislava, Budapest, Ljubljana, Prague 056 set("Central European Standard Time",TimeZoneConstants.CET); // (GMT+01:00) Sarajevo, Skopje, Warsaw, Zagreb 057 set("Romance Standard Time",TimeZoneConstants.EUROPE_BRUSSELS); // (GMT+01:00) Brussels, Copenhagen, Madrid, Paris 058 set("W. Europe Standard Time",TimeZoneConstants.CET); // (GMT+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna 059 set("W. Central Africa Standard Time",null); // (GMT+01:00) West Central Africa 060 set("E. Europe Standard Time",TimeZoneConstants.ART); // (GMT+02:00) Bucharest 061 set("Egypt Standard Time",TimeZoneConstants.EGYPT); // (GMT+02:00) Cairo 062 set("FLE Standard Time",TimeZoneConstants.EET); // (GMT+02:00) Helsinki, Kiev, Riga, Sofia, Tallinn, Vilnius 063 set("GTB Standard Time",TimeZoneConstants.EUROPE_ATHENS); // (GMT+02:00) Athens, Istanbul, Minsk 064 set("Israel Standard Time",TimeZoneConstants.ASIA_JERUSALEM); // (GMT+02:00) Jerusalem 065 set("South Africa Standard Time",TimeZoneConstants.AFRICA_JOHANNESBURG); // (GMT+02:00) Harare, Pretoria 066 set("Russian Standard Time",TimeZoneConstants.EUROPE_MOSCOW); // (GMT+03:00) Moscow, St. Petersburg, Volgograd 067 set("Arab Standard Time",TimeZoneConstants.ASIA_KUWAIT); // (GMT+03:00) Kuwait, Riyadh 068 set("E. Africa Standard Time",TimeZoneConstants.AFRICA_NAIROBI); // (GMT+03:00) Nairobi 069 set("Arabic Standard Time",TimeZoneConstants.ASIA_BAGHDAD); // (GMT+03:00) Baghdad 070 set("Iran Standard Time",TimeZoneConstants.ASIA_TEHRAN); // (GMT+03:30) Tehran 071 set("Arabian Standard Time",TimeZoneConstants.ASIA_MUSCAT); // (GMT+04:00) Abu Dhabi, Muscat 072 set("Caucasus Standard Time",TimeZoneConstants.ASIA_YEREVAN); // (GMT+04:00) Baku, Tbilisi, Yerevan 073 set("Transitional Islamic State of Afghanistan Standard Time",TimeZoneConstants.ASIA_KABUL); // (GMT+04:30) Kabul 074 set("Ekaterinburg Standard Time",TimeZoneConstants.ASIA_YEKATERINBURG); // (GMT+05:00) Ekaterinburg 075 set("West Asia Standard Time",TimeZoneConstants.ASIA_KARACHI); // (GMT+05:00) Islamabad, Karachi, Tashkent 076 set("India Standard Time",TimeZoneConstants.IST); // (GMT+05:30) Chennai, Kolkata, Mumbai, New Delhi 077 set("Nepal Standard Time",TimeZoneConstants.ASIA_KATMANDU); // (GMT+05:45) Kathmandu 078 set("Central Asia Standard Time",TimeZoneConstants.ASIA_DHAKA); //(GMT+06:00) Astana, Dhaka 079 set("Sri Lanka Standard Time",TimeZoneConstants.ASIA_COLOMBO); // (GMT+06:00) Sri Jayawardenepura 080 set("N. Central Asia Standard Time",TimeZoneConstants.ASIA_ALMATY); // (GMT+06:00) Almaty, Novosibirsk 081 set("Myanmar Standard Time",TimeZoneConstants.ASIA_RANGOON); // (GMT+06:30) Yangon Rangoon 082 set("S.E. Asia Standard Time",TimeZoneConstants.ASIA_BANGKOK); // (GMT+07:00) Bangkok, Hanoi, Jakarta 083 set("North Asia Standard Time",TimeZoneConstants.ASIA_KRASNOYARSK); // (GMT+07:00) Krasnoyarsk 084 set("China Standard Time",TimeZoneConstants.CTT); // (GMT+08:00) Beijing, Chongqing, Hong Kong SAR, Urumqi 085 set("Singapore Standard Time",TimeZoneConstants.ASIA_SINGAPORE); // (GMT+08:00) Kuala Lumpur, Singapore 086 set("Taipei Standard Time",TimeZoneConstants.ASIA_TAIPEI); // (GMT+08:00) Taipei 087 set("W. Australia Standard Time",TimeZoneConstants.AUSTRALIA_PERTH); // (GMT+08:00) Perth 088 set("North Asia East Standard Time",TimeZoneConstants.ASIA_IRKUTSK); // (GMT+08:00) Irkutsk, Ulaanbaatar 089 set("Korea Standard Time",TimeZoneConstants.ASIA_SEOUL); // (GMT+09:00) Seoul 090 set("Tokyo Standard Time",TimeZoneConstants.ASIA_TOKYO); // (GMT+09:00) Osaka, Sapporo, Tokyo 091 set("Yakutsk Standard Time",TimeZoneConstants.ASIA_YAKUTSK); // (GMT+09:00) Yakutsk 092 set("A.U.S. Central Standard Time",TimeZoneConstants.ACT); // (GMT+09:30) Darwin 093 set("Cen. Australia Standard Time",TimeZoneConstants.ACT); // (GMT+09:30) Adelaide 094 set("A.U.S. Eastern Standard Time",TimeZoneConstants.AET); // (GMT+10:00) Canberra, Melbourne, Sydney 095 set("E. Australia Standard Time",TimeZoneConstants.AET); // (GMT+10:00) Brisbane 096 set("Tasmania Standard Time",TimeZoneConstants.AUSTRALIA_TASMANIA); // (GMT+10:00) Hobart 097 set("Vladivostok Standard Time",TimeZoneConstants.ASIA_VLADIVOSTOK); // (GMT+10:00) Vladivostok 098 set("West Pacific Standard Time",TimeZoneConstants.PACIFIC_GUAM); // (GMT+10:00) Guam, Port Moresby 099 set("Central Pacific Standard Time",TimeZoneConstants.ASIA_MAGADAN); // (GMT+11:00) Magadan, Solomon Islands, New Caledonia 100 set("Fiji Islands Standard Time",TimeZoneConstants.PACIFIC_FIJI); // (GMT+12:00) Fiji Islands, Kamchatka, Marshall Islands 101 set("New Zealand Standard Time",TimeZoneConstants.NZ); // (GMT+12:00) Auckland, Wellington 102 set("Tonga Standard Time",TimeZoneConstants.PACIFIC_TONGATAPU); // (GMT+13:00) Nuku'alofa 103 104 105 } 106 107 private static void set(String name, TimeZone tz) { 108 if(tz==null) return; 109 name=StringUtil.replace(name.trim().toLowerCase(), " ", "", false); 110 IDS.put(name.toLowerCase(), tz); 111 } 112 113 /** 114 * return the string format of the Timezone 115 * @param timezone 116 * @return 117 */ 118 public static String toString(TimeZone timezone){ 119 return timezone.getID(); 120 } 121 122 private static String getSupportedTimeZonesAsString() { 123 return ListUtil.arrayToList(TimeZone.getAvailableIDs(),", "); 124 } 125 126 /** 127 * translate timezone string format to a timezone 128 * @param strTimezone 129 * @return 130 */ 131 public static TimeZone toTimeZone(String strTimezone,TimeZone defaultValue){ 132 if(strTimezone==null) return defaultValue; 133 strTimezone=StringUtil.replace(strTimezone.trim().toLowerCase(), " ", "", false); 134 TimeZone tz = IDS.get(strTimezone); 135 if(tz!=null) return tz; 136 137 //parse GMT followd by a number 138 float gmtOffset=Float.NaN; 139 if(strTimezone.startsWith("gmt")) gmtOffset=getGMTOffset(strTimezone.substring(3).trim(),Float.NaN); 140 else if(strTimezone.startsWith("etc/gmt")) gmtOffset=getGMTOffset(strTimezone.substring(7).trim(),Float.NaN); 141 else if(strTimezone.startsWith("utc")) gmtOffset=getGMTOffset(strTimezone.substring(3).trim(),Float.NaN); 142 else if(strTimezone.startsWith("etc/utc")) gmtOffset=getGMTOffset(strTimezone.substring(7).trim(),Float.NaN); 143 144 145 146 if(!Float.isNaN(gmtOffset)) { 147 strTimezone="etc/gmt"+(gmtOffset>=0?"+":"")+Caster.toString(gmtOffset); 148 tz = IDS.get(strTimezone); 149 if(tz!=null) return tz; 150 151 } 152 153 154 155 156 return defaultValue; 157 } 158 159 private static float getGMTOffset(String str, float defaultValue) { 160 int index; 161 String left=null,right=null; 162 if((index=str.indexOf(':'))!=-1) { 163 left = str.substring(0,index); 164 right=str.substring(index+1); 165 } 166 else if(str.startsWith("-")) { 167 if(str.length()>=4 && str.indexOf('.')==-1){ 168 left = str.substring(0,str.length()-2); 169 right=str.substring(str.length()-2); 170 } 171 } 172 else if(str.length()>=3 && str.indexOf('.')==-1) { 173 left = str.substring(0,str.length()-2); 174 right=str.substring(str.length()-2); 175 } 176 if(left!=null) { 177 int l = Caster.toIntValue(left,Integer.MIN_VALUE); 178 int r = Caster.toIntValue(right,Integer.MIN_VALUE); 179 if(l==Integer.MIN_VALUE || r==Integer.MIN_VALUE || r>59) return defaultValue; 180 return l+(r/60f); 181 } 182 183 184 float f=Caster.toFloatValue(str,Float.NaN); 185 if(Float.isNaN(f)) return defaultValue; 186 return f; 187 } 188 189 public static TimeZone toTimeZone(String strTimezone) throws ExpressionException{ 190 TimeZone tz = toTimeZone(strTimezone, null); 191 if(tz!=null) return tz; 192 throw new ExpressionException("can't cast value ("+strTimezone+") to a TimeZone","supported TimeZones are:"+getSupportedTimeZonesAsString()); 193 } 194 195 public static Calendar getCalendar(TimeZone tz) { 196 return Calendar.getInstance(ThreadLocalPageContext.getTimeZone(tz)); 197 } 198 }