From 1e49f6c35f2a2c0133f9e331ebb84f96d34cef4c Mon Sep 17 00:00:00 2001 From: Neil Fuller Date: Fri, 31 Mar 2017 13:05:01 +0100 Subject: [PATCH] Remove time_zones_by_country.xml file time_zones_by_country.xml has been replaced by a file that can be updated outside of an OTA and can be accessed via libcore.util.TimeZoneFinder. This means parsing code has been removed from this class and replaced by calls to libcore code. libcore code uses ICU so this class adapts to java.util.TimeZone for published public APIs as well as other knock-ons to reduce impact of this change in telephony code. All use of classes called TimeZone are fully-qualified to reduce confusion. Several public-but-hidden methods have been removed. These can be returned if there are any important apps relying on them. Bug: 25338903 Test: Ran CtsUtilTestCases Change-Id: I699b4e7420e8d7e61ee68ec96552ab3144c9bab2 --- core/java/android/util/TimeUtils.java | 178 +-- core/res/res/values/symbols.xml | 1 - core/res/res/xml/time_zones_by_country.xml | 1372 -------------------- 3 files changed, 58 insertions(+), 1493 deletions(-) delete mode 100644 core/res/res/xml/time_zones_by_country.xml diff --git a/core/java/android/util/TimeUtils.java b/core/java/android/util/TimeUtils.java index 37d675707a84b..2b03ed6c3ae13 100644 --- a/core/java/android/util/TimeUtils.java +++ b/core/java/android/util/TimeUtils.java @@ -16,25 +16,17 @@ package android.util; -import android.content.res.Resources; -import android.content.res.XmlResourceParser; import android.os.SystemClock; -import android.text.format.DateUtils; -import com.android.internal.util.XmlUtils; - -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; - -import java.io.IOException; import java.io.PrintWriter; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.Collection; +import java.util.Collections; import java.util.Date; -import java.util.TimeZone; - +import java.util.List; +import libcore.util.TimeZoneFinder; import libcore.util.ZoneInfoDB; /** @@ -45,14 +37,9 @@ public class TimeUtils { private static final boolean DBG = false; private static final String TAG = "TimeUtils"; - /** Cached results of getTineZones */ - private static final Object sLastLockObj = new Object(); - private static ArrayList sLastZones = null; - private static String sLastCountry = null; - /** Cached results of getTimeZonesWithUniqueOffsets */ private static final Object sLastUniqueLockObj = new Object(); - private static ArrayList sLastUniqueZoneOffsets = null; + private static List sLastUniqueZoneOffsets = null; private static String sLastUniqueCountry = null; /** {@hide} */ @@ -63,50 +50,39 @@ public class TimeUtils { * and DST value at the specified moment in the specified country. * Returns null if no suitable zone could be found. */ - public static TimeZone getTimeZone(int offset, boolean dst, long when, String country) { - TimeZone best = null; - final Date d = new Date(when); + public static java.util.TimeZone getTimeZone( + int offset, boolean dst, long when, String country) { - TimeZone current = TimeZone.getDefault(); - String currentName = current.getID(); - int currentOffset = current.getOffset(when); - boolean currentDst = current.inDaylightTime(d); - - for (TimeZone tz : getTimeZones(country)) { - // If the current time zone is from the right country - // and meets the other known properties, keep it - // instead of changing to another one. - - if (tz.getID().equals(currentName)) { - if (currentOffset == offset && currentDst == dst) { - return current; - } - } - - // Otherwise, take the first zone from the right - // country that has the correct current offset and DST. - // (Keep iterating instead of returning in case we - // haven't encountered the current time zone yet.) - - if (best == null) { - if (tz.getOffset(when) == offset && - tz.inDaylightTime(d) == dst) { - best = tz; - } - } - } - - return best; + android.icu.util.TimeZone icuTimeZone = getIcuTimeZone(offset, dst, when, country); + // We must expose a java.util.TimeZone here for API compatibility because this is a public + // API method. + return icuTimeZone != null ? java.util.TimeZone.getTimeZone(icuTimeZone.getID()) : null; } /** - * Return list of unique time zones for the country. Do not modify + * Tries to return a frozen ICU time zone that would have had the specified offset + * and DST value at the specified moment in the specified country. + * Returns null if no suitable zone could be found. + */ + private static android.icu.util.TimeZone getIcuTimeZone( + int offset, boolean dst, long when, String country) { + if (country == null) { + return null; + } + + android.icu.util.TimeZone bias = android.icu.util.TimeZone.getDefault(); + return TimeZoneFinder.getInstance() + .lookupTimeZoneByCountryAndOffset(country, offset, dst, when, bias); + } + + /** + * Returns an immutable list of unique time zone IDs for the country. * * @param country to find - * @return list of unique time zones, maybe empty but never null. Do not modify. + * @return unmodifiable list of unique time zones, maybe empty but never null. * @hide */ - public static ArrayList getTimeZonesWithUniqueOffsets(String country) { + public static List getTimeZoneIdsWithUniqueOffsets(String country) { synchronized(sLastUniqueLockObj) { if ((country != null) && country.equals(sLastUniqueCountry)) { if (DBG) { @@ -117,9 +93,9 @@ public class TimeUtils { } } - Collection zones = getTimeZones(country); - ArrayList uniqueTimeZones = new ArrayList(); - for (TimeZone zone : zones) { + Collection zones = getIcuTimeZones(country); + ArrayList uniqueTimeZones = new ArrayList<>(); + for (android.icu.util.TimeZone zone : zones) { // See if we already have this offset, // Using slow but space efficient and these are small. boolean found = false; @@ -129,7 +105,7 @@ public class TimeUtils { break; } } - if (found == false) { + if (!found) { if (DBG) { Log.d(TAG, "getTimeZonesWithUniqueOffsets: add unique offset=" + zone.getRawOffset() + " zone.getID=" + zone.getID()); @@ -140,81 +116,43 @@ public class TimeUtils { synchronized(sLastUniqueLockObj) { // Cache the last result - sLastUniqueZoneOffsets = uniqueTimeZones; + sLastUniqueZoneOffsets = extractZoneIds(uniqueTimeZones); sLastUniqueCountry = country; return sLastUniqueZoneOffsets; } } + private static List extractZoneIds(List timeZones) { + List ids = new ArrayList<>(timeZones.size()); + for (android.icu.util.TimeZone timeZone : timeZones) { + ids.add(timeZone.getID()); + } + return Collections.unmodifiableList(ids); + } + /** - * Returns the time zones for the country, which is the code - * attribute of the timezone element in time_zones_by_country.xml. Do not modify. + * Returns an immutable list of frozen ICU time zones for the country. * - * @param country is a two character country code. - * @return TimeZone list, maybe empty but never null. Do not modify. + * @param countryIso is a two character country code. + * @return TimeZone list, maybe empty but never null. * @hide */ - public static ArrayList getTimeZones(String country) { - synchronized (sLastLockObj) { - if ((country != null) && country.equals(sLastCountry)) { - if (DBG) Log.d(TAG, "getTimeZones(" + country + "): return cached version"); - return sLastZones; + private static List getIcuTimeZones(String countryIso) { + if (countryIso == null) { + if (DBG) Log.d(TAG, "getIcuTimeZones(null): return empty list"); + return Collections.emptyList(); + } + List timeZones = + TimeZoneFinder.getInstance().lookupTimeZonesByCountry(countryIso); + if (timeZones == null) { + if (DBG) { + Log.d(TAG, "getIcuTimeZones(" + countryIso + + "): returned null, converting to empty list"); } + return Collections.emptyList(); } - - ArrayList tzs = new ArrayList(); - - if (country == null) { - if (DBG) Log.d(TAG, "getTimeZones(null): return empty list"); - return tzs; - } - - Resources r = Resources.getSystem(); - XmlResourceParser parser = r.getXml(com.android.internal.R.xml.time_zones_by_country); - - try { - XmlUtils.beginDocument(parser, "timezones"); - - while (true) { - XmlUtils.nextElement(parser); - - String element = parser.getName(); - if (element == null || !(element.equals("timezone"))) { - break; - } - - String code = parser.getAttributeValue(null, "code"); - - if (country.equals(code)) { - if (parser.next() == XmlPullParser.TEXT) { - String zoneIdString = parser.getText(); - TimeZone tz = TimeZone.getTimeZone(zoneIdString); - if (tz.getID().startsWith("GMT") == false) { - // tz.getID doesn't start not "GMT" so its valid - tzs.add(tz); - if (DBG) { - Log.d(TAG, "getTimeZone('" + country + "'): found tz.getID==" - + ((tz != null) ? tz.getID() : "")); - } - } - } - } - } - } catch (XmlPullParserException e) { - Log.e(TAG, "Got xml parser exception getTimeZone('" + country + "'): e=", e); - } catch (IOException e) { - Log.e(TAG, "Got IO exception getTimeZone('" + country + "'): e=", e); - } finally { - parser.close(); - } - - synchronized(sLastLockObj) { - // Cache the last result; - sLastZones = tzs; - sLastCountry = country; - return sLastZones; - } + return timeZones; } /** diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index f3ce7190ca7f5..270a215ef5ec8 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -1433,7 +1433,6 @@ - diff --git a/core/res/res/xml/time_zones_by_country.xml b/core/res/res/xml/time_zones_by_country.xml deleted file mode 100644 index 22bfea191d964..0000000000000 --- a/core/res/res/xml/time_zones_by_country.xml +++ /dev/null @@ -1,1372 +0,0 @@ - - - - - - Europe/Andorra - - - - Asia/Dubai - - - - Asia/Kabul - - - - America/Antigua - - - - America/Anguilla - - - - Europe/Tirane - - - - Asia/Yerevan - - - - Africa/Luanda - - - - Antarctica/McMurdo - - - - Antarctica/DumontDUrville - - - - Antarctica/Casey - - - - Antarctica/Davis - - - - Antarctica/Mawson - - - - Antarctica/Vostok - - - - Antarctica/Syowa - - - - Antarctica/Troll - - - - Antarctica/Rothera - - - - Antarctica/Palmer - - - - America/Argentina/Buenos_Aires - America/Argentina/Cordoba - America/Argentina/Salta - America/Argentina/Jujuy - America/Argentina/Tucuman - America/Argentina/Catamarca - America/Argentina/La_Rioja - America/Argentina/San_Juan - America/Argentina/Mendoza - America/Argentina/San_Luis - America/Argentina/Rio_Gallegos - America/Argentina/Ushuaia - - - - Pacific/Pago_Pago - - - - Europe/Vienna - - - - Australia/Sydney - Australia/Melbourne - Australia/Brisbane - Australia/Hobart - Australia/Currie - Australia/Lindeman - - - Antarctica/Macquarie - - - - Australia/Lord_Howe - - - - Australia/Adelaide - Australia/Broken_Hill - Australia/Darwin - - - - Australia/Perth - - - - Australia/Eucla - - - - America/Aruba - - - - Europe/Mariehamn - - - - Asia/Baku - - - - Europe/Sarajevo - - - - America/Barbados - - - - Asia/Dhaka - - - - Europe/Brussels - - - - Africa/Ouagadougou - - - - Europe/Sofia - - - - Asia/Bahrain - - - - Africa/Bujumbura - - - - Africa/Porto-Novo - - - - America/St_Barthelemy - - - - Atlantic/Bermuda - - - - Asia/Brunei - - - - America/La_Paz - - - - America/Kralendijk - - - - America/Noronha - - - - America/Sao_Paulo - America/Belem - America/Fortaleza - America/Recife - America/Araguaina - America/Maceio - America/Bahia - America/Santarem - - - - America/Manaus - America/Campo_Grande - America/Cuiaba - America/Porto_Velho - America/Boa_Vista - - - - America/Eirunepe - America/Rio_Branco - - - - America/Nassau - - - - Asia/Thimphu - - - - Africa/Gaborone - - - - Europe/Minsk - - - - America/Belize - - - - America/St_Johns - - - - America/Halifax - America/Glace_Bay - America/Moncton - America/Goose_Bay - America/Blanc-Sablon - - - - America/Toronto - America/Nipigon - America/Thunder_Bay - America/Iqaluit - America/Pangnirtung - America/Atikokan - - - - America/Winnipeg - America/Regina - America/Rankin_Inlet - America/Rainy_River - America/Swift_Current - America/Resolute - - - - America/Edmonton - America/Cambridge_Bay - America/Yellowknife - America/Inuvik - America/Dawson_Creek - America/Creston - America/Fort_Nelson - - - - America/Vancouver - America/Whitehorse - America/Dawson - - - - Indian/Cocos - - - - Africa/Lubumbashi - - - - Africa/Kinshasa - - - - Africa/Bangui - - - - Africa/Brazzaville - - - - Europe/Zurich - - - - Africa/Abidjan - - - - Pacific/Rarotonga - - - - America/Punta_Arenas - - - - America/Santiago - - - - Pacific/Easter - - - - Africa/Douala - - - - Asia/Shanghai - - - - Asia/Urumqi - - - - America/Bogota - - - - America/Costa_Rica - - - - America/Havana - - - - Atlantic/Cape_Verde - - - - America/Curacao - - - - Indian/Christmas - - - - Asia/Nicosia - - - - Asia/Famagusta - - - - Europe/Prague - - - - Europe/Berlin - Europe/Busingen - - - - Africa/Djibouti - - - - Europe/Copenhagen - - - - America/Dominica - - - - America/Santo_Domingo - - - - Africa/Algiers - - - - America/Guayaquil - - - - Pacific/Galapagos - - - - Europe/Tallinn - - - - Africa/Cairo - - - - Africa/El_Aaiun - - - - Africa/Asmara - - - - Europe/Madrid - Africa/Ceuta - - - - Atlantic/Canary - - - - Africa/Addis_Ababa - - - - Europe/Helsinki - - - - Pacific/Fiji - - - - Atlantic/Stanley - - - - Pacific/Pohnpei - Pacific/Kosrae - - - - Pacific/Chuuk - - - - Atlantic/Faroe - - - - Europe/Paris - - - - Africa/Libreville - - - - Europe/London - - - - America/Grenada - - - - Asia/Tbilisi - - - - America/Cayenne - - - - Europe/Guernsey - - - - Africa/Accra - - - - Europe/Gibraltar - - - - America/Danmarkshavn - - - - America/Scoresbysund - - - - America/Godthab - - - - America/Thule - - - - Africa/Banjul - - - - Africa/Conakry - - - - America/Guadeloupe - - - - Africa/Malabo - - - - Europe/Athens - - - - Atlantic/South_Georgia - - - - America/Guatemala - - - - Pacific/Guam - - - - Africa/Bissau - - - - America/Guyana - - - - Asia/Hong_Kong - - - - America/Tegucigalpa - - - - Europe/Zagreb - - - - America/Port-au-Prince - - - - Europe/Budapest - - - - Asia/Jayapura - - - - Asia/Makassar - - - - Asia/Jakarta - Asia/Pontianak - - - - Europe/Dublin - - - - Asia/Jerusalem - - - - Europe/Isle_of_Man - - - - Asia/Kolkata - - - - Indian/Chagos - - - - Asia/Baghdad - - - - Asia/Tehran - - - - Atlantic/Reykjavik - - - - Europe/Rome - - - - Europe/Jersey - - - - America/Jamaica - - - - Asia/Amman - - - - Asia/Tokyo - - - - Africa/Nairobi - - - - Asia/Bishkek - - - - Asia/Phnom_Penh - - - - Pacific/Kiritimati - - - - Pacific/Enderbury - - - - Pacific/Tarawa - - - - Indian/Comoro - - - - America/St_Kitts - - - - Asia/Pyongyang - - - - Asia/Seoul - - - - Asia/Kuwait - - - - America/Cayman - - - - Asia/Almaty - Asia/Qyzylorda - - - - Asia/Aqtau - Asia/Oral - Asia/Aqtobe - Asia/Atyrau - - - - Asia/Vientiane - - - - Asia/Beirut - - - - America/St_Lucia - - - - Europe/Vaduz - - - - Asia/Colombo - - - - Africa/Monrovia - - - - Africa/Maseru - - - - Europe/Vilnius - - - - Europe/Luxembourg - - - - Europe/Riga - - - - Africa/Tripoli - - - - Africa/Casablanca - - - - Europe/Monaco - - - - Europe/Chisinau - - - - Europe/Podgorica - - - - America/Marigot - - - - Indian/Antananarivo - - - - Pacific/Majuro - Pacific/Kwajalein - - - - Europe/Skopje - - - - Africa/Bamako - - - - Asia/Yangon - - - - Asia/Choibalsan - Asia/Ulaanbaatar - - - - Asia/Hovd - - - - Asia/Macau - - - - Pacific/Saipan - - - - America/Martinique - - - - Africa/Nouakchott - - - - America/Montserrat - - - - Europe/Malta - - - - Indian/Mauritius - - - - Indian/Maldives - - - - Africa/Blantyre - - - - America/Mexico_City - America/Merida - America/Monterrey - America/Matamoros - America/Bahia_Banderas - - - - America/Cancun - - - - America/Chihuahua - America/Hermosillo - America/Mazatlan - America/Ojinaga - - - - America/Tijuana - - - - Asia/Kuala_Lumpur - Asia/Kuching - - - - Africa/Maputo - - - - Africa/Windhoek - - - - Pacific/Noumea - - - - Africa/Niamey - - - - Pacific/Norfolk - - - - Africa/Lagos - - - - America/Managua - - - - Europe/Amsterdam - - - - Europe/Oslo - - - - Asia/Kathmandu - - - - Pacific/Nauru - - - - Pacific/Niue - - - - Pacific/Auckland - - - - Pacific/Chatham - - - - Asia/Muscat - - - - America/Panama - - - - America/Lima - - - - Pacific/Gambier - - - - Pacific/Marquesas - - - - Pacific/Tahiti - - - - Pacific/Port_Moresby - - - - Pacific/Bougainville - - - - Asia/Manila - - - - Asia/Karachi - - - - Europe/Warsaw - - - - America/Miquelon - - - - Pacific/Pitcairn - - - - America/Puerto_Rico - - - - Asia/Gaza - Asia/Hebron - - - - Europe/Lisbon - Atlantic/Madeira - - - - Atlantic/Azores - - - - Pacific/Palau - - - - America/Asuncion - - - - Asia/Qatar - - - - Indian/Reunion - - - - Europe/Bucharest - - - - Europe/Belgrade - - - - Asia/Kamchatka - Asia/Anadyr - - - - Asia/Magadan - Asia/Sakhalin - Asia/Srednekolymsk - - - - Asia/Vladivostok - Asia/Ust-Nera - - - - Asia/Yakutsk - Asia/Chita - Asia/Khandyga - - - - Asia/Irkutsk - - - - Asia/Krasnoyarsk - Asia/Novosibirsk - Asia/Barnaul - Asia/Novokuznetsk - Asia/Tomsk - - - - Asia/Omsk - - - - Asia/Yekaterinburg - - - - Europe/Samara - Europe/Astrakhan - Europe/Ulyanovsk - Europe/Saratov - - - - Europe/Moscow - Europe/Volgograd - Europe/Kirov - Europe/Simferopol - - - - Europe/Kaliningrad - - - - Africa/Kigali - - - - Asia/Riyadh - - - - Pacific/Guadalcanal - - - - Indian/Mahe - - - - Africa/Khartoum - - - - Europe/Stockholm - - - - Asia/Singapore - - - - Atlantic/St_Helena - - - - Europe/Ljubljana - - - - Arctic/Longyearbyen - - - - Europe/Bratislava - - - - Africa/Freetown - - - - Europe/San_Marino - - - - Africa/Dakar - - - - Africa/Mogadishu - - - - America/Paramaribo - - - - Africa/Juba - - - - Africa/Sao_Tome - - - - America/El_Salvador - - - - America/Lower_Princes - - - - Asia/Damascus - - - - Africa/Mbabane - - - - America/Grand_Turk - - - - Africa/Ndjamena - - - - Indian/Kerguelen - - - - Africa/Lome - - - - Asia/Bangkok - - - - Asia/Dushanbe - - - - Pacific/Fakaofo - - - - Asia/Dili - - - - Asia/Ashgabat - - - - Africa/Tunis - - - - Pacific/Tongatapu - - - - Europe/Istanbul - - - - America/Port_of_Spain - - - - Pacific/Funafuti - - - - Asia/Taipei - - - - Africa/Dar_es_Salaam - - - - Europe/Kiev - Europe/Uzhgorod - Europe/Zaporozhye - - - - Africa/Kampala - - - - Pacific/Wake - - - - Pacific/Midway - - - - America/New_York - America/Detroit - America/Kentucky/Louisville - America/Kentucky/Monticello - America/Indiana/Indianapolis - America/Indiana/Vincennes - America/Indiana/Winamac - America/Indiana/Marengo - America/Indiana/Petersburg - America/Indiana/Vevay - - - - America/Chicago - America/Indiana/Knox - America/Menominee - America/North_Dakota/Center - America/North_Dakota/New_Salem - America/Indiana/Tell_City - America/North_Dakota/Beulah - - - - America/Denver - America/Boise - America/Phoenix - - - - America/Los_Angeles - - - - America/Anchorage - America/Juneau - America/Yakutat - America/Nome - America/Metlakatla - America/Sitka - - - - Pacific/Honolulu - America/Adak - - - - America/Montevideo - - - - Asia/Tashkent - Asia/Samarkand - - - - Europe/Vatican - - - - America/St_Vincent - - - - America/Caracas - - - - America/Tortola - - - - America/St_Thomas - - - - Asia/Ho_Chi_Minh - - - - Pacific/Efate - - - - Pacific/Wallis - - - - Pacific/Apia - - - - Asia/Aden - - - - Indian/Mayotte - - - - Africa/Johannesburg - - - - Africa/Lusaka - - - - Africa/Harare -