1b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan/* 2b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan * Copyright (C) 2013 The Android Open Source Project 3b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan * 4b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan * Licensed under the Apache License, Version 2.0 (the "License"); 5b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan * you may not use this file except in compliance with the License. 6b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan * You may obtain a copy of the License at 7b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan * 8b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan * http://www.apache.org/licenses/LICENSE-2.0 9b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan * 10b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan * Unless required by applicable law or agreed to in writing, software 11b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan * distributed under the License is distributed on an "AS IS" BASIS, 12b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan * See the License for the specific language governing permissions and 14b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan * limitations under the License. 15b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan */ 16b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 17b1b7080deea42aa533c3757b585cf765c6b76732Michael Chanpackage com.android.timezonepicker; 18b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 19b1b7080deea42aa533c3757b585cf765c6b76732Michael Chanimport android.content.Context; 20b1b7080deea42aa533c3757b585cf765c6b76732Michael Chanimport android.content.res.AssetManager; 211989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chanimport android.content.res.Resources; 22b1b7080deea42aa533c3757b585cf765c6b76732Michael Chanimport android.text.format.DateFormat; 23b1b7080deea42aa533c3757b585cf765c6b76732Michael Chanimport android.text.format.DateUtils; 24b1b7080deea42aa533c3757b585cf765c6b76732Michael Chanimport android.util.Log; 25b1b7080deea42aa533c3757b585cf765c6b76732Michael Chanimport android.util.SparseArray; 26b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 27b1b7080deea42aa533c3757b585cf765c6b76732Michael Chanimport java.io.BufferedReader; 28b1b7080deea42aa533c3757b585cf765c6b76732Michael Chanimport java.io.IOException; 29b1b7080deea42aa533c3757b585cf765c6b76732Michael Chanimport java.io.InputStream; 30b1b7080deea42aa533c3757b585cf765c6b76732Michael Chanimport java.io.InputStreamReader; 31b1b7080deea42aa533c3757b585cf765c6b76732Michael Chanimport java.util.ArrayList; 32b1b7080deea42aa533c3757b585cf765c6b76732Michael Chanimport java.util.Collections; 33b1b7080deea42aa533c3757b585cf765c6b76732Michael Chanimport java.util.Date; 34b1b7080deea42aa533c3757b585cf765c6b76732Michael Chanimport java.util.HashMap; 35b1b7080deea42aa533c3757b585cf765c6b76732Michael Chanimport java.util.HashSet; 36b1b7080deea42aa533c3757b585cf765c6b76732Michael Chanimport java.util.LinkedHashMap; 37b1b7080deea42aa533c3757b585cf765c6b76732Michael Chanimport java.util.Locale; 38b1b7080deea42aa533c3757b585cf765c6b76732Michael Chanimport java.util.TimeZone; 39b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 40b1b7080deea42aa533c3757b585cf765c6b76732Michael Chanpublic class TimeZoneData { 41b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan private static final String TAG = "TimeZoneData"; 42b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan private static final boolean DEBUG = false; 43b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan private static final int OFFSET_ARRAY_OFFSET = 20; 44b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 4562e91b1a6e5decfbe7206a381fed5ff9bb08785bSam Blitzstein private static final String PALESTINE_COUNTRY_CODE = "PS"; 4662e91b1a6e5decfbe7206a381fed5ff9bb08785bSam Blitzstein 4762e91b1a6e5decfbe7206a381fed5ff9bb08785bSam Blitzstein 48b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan ArrayList<TimeZoneInfo> mTimeZones; 49b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan LinkedHashMap<String, ArrayList<Integer>> mTimeZonesByCountry; 50b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan HashSet<String> mTimeZoneNames = new HashSet<String>(); 51b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 52b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan private long mTimeMillis; 53b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan private HashMap<String, String> mCountryCodeToNameMap = new HashMap<String, String>(); 54b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 55b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan public String mDefaultTimeZoneId; 56b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan public static boolean is24HourFormat; 57b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan private TimeZoneInfo mDefaultTimeZoneInfo; 58b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan private String mAlternateDefaultTimeZoneId; 59b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan private String mDefaultTimeZoneCountry; 601989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan private HashMap<String, TimeZoneInfo> mTimeZonesById; 611989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan private boolean[] mHasTimeZonesInHrOffset = new boolean[40]; 621989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan SparseArray<ArrayList<Integer>> mTimeZonesByOffsets; 631989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan private Context mContext; 6462e91b1a6e5decfbe7206a381fed5ff9bb08785bSam Blitzstein private String mPalestineDisplayName; 65b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 66b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan public TimeZoneData(Context context, String defaultTimeZoneId, long timeMillis) { 671989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan mContext = context; 68b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan is24HourFormat = TimeZoneInfo.is24HourFormat = DateFormat.is24HourFormat(context); 69b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan mDefaultTimeZoneId = mAlternateDefaultTimeZoneId = defaultTimeZoneId; 70b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan long now = System.currentTimeMillis(); 71b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 72b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan if (timeMillis == 0) { 73b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan mTimeMillis = now; 74b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } else { 75b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan mTimeMillis = timeMillis; 76b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 7762e91b1a6e5decfbe7206a381fed5ff9bb08785bSam Blitzstein 7862e91b1a6e5decfbe7206a381fed5ff9bb08785bSam Blitzstein mPalestineDisplayName = context.getResources().getString(R.string.palestine_display_name); 7962e91b1a6e5decfbe7206a381fed5ff9bb08785bSam Blitzstein 80b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan loadTzs(context); 811989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan 82b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan Log.i(TAG, "Time to load time zones (ms): " + (System.currentTimeMillis() - now)); 83b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 84b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // now = System.currentTimeMillis(); 85b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // printTz(); 86b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // Log.i(TAG, "Time to print time zones (ms): " + 87b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // (System.currentTimeMillis() - now)); 88b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 89b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 90b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan public void setTime(long timeMillis) { 91b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan mTimeMillis = timeMillis; 92b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 93b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 94b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan public TimeZoneInfo get(int position) { 95b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan return mTimeZones.get(position); 96b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 97b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 98b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan public int size() { 99b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan return mTimeZones.size(); 100b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 101b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 102b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan public int getDefaultTimeZoneIndex() { 103b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan return mTimeZones.indexOf(mDefaultTimeZoneInfo); 104b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 105b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 106b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // TODO speed this up 107b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan public int findIndexByTimeZoneIdSlow(String timeZoneId) { 108b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan int idx = 0; 109b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan for (TimeZoneInfo tzi : mTimeZones) { 110b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan if (timeZoneId.equals(tzi.mTzId)) { 111b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan return idx; 112b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 113b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan idx++; 114b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 115b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan return -1; 116b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 117b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 118b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan void loadTzs(Context context) { 119b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan mTimeZones = new ArrayList<TimeZoneInfo>(); 120b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan HashSet<String> processedTimeZones = loadTzsInZoneTab(context); 121b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan String[] tzIds = TimeZone.getAvailableIDs(); 122b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 123b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan if (DEBUG) { 124b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan Log.e(TAG, "Available time zones: " + tzIds.length); 125b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 126b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 127b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan for (String tzId : tzIds) { 128b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan if (processedTimeZones.contains(tzId)) { 129b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan continue; 130b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 131b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 1321989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan /* 1333d4445bb2a85048a735f21f7ec3ee9f9af6cee22Michael Chan * Dropping non-GMT tzs without a country code. They are not really 1343d4445bb2a85048a735f21f7ec3ee9f9af6cee22Michael Chan * needed and they are dups but missing proper country codes. e.g. 1353d4445bb2a85048a735f21f7ec3ee9f9af6cee22Michael Chan * WET CET MST7MDT PST8PDT Asia/Khandyga Asia/Ust-Nera EST 1361989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan */ 1371989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan if (!tzId.startsWith("Etc/GMT")) { 1381989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan continue; 1391989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan } 1401989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan 141b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan final TimeZone tz = TimeZone.getTimeZone(tzId); 142b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan if (tz == null) { 143b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan Log.e(TAG, "Timezone not found: " + tzId); 144b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan continue; 145b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 146b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 147b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan TimeZoneInfo tzInfo = new TimeZoneInfo(tz, null); 148b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 149b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan if (getIdenticalTimeZoneInTheCountry(tzInfo) == -1) { 150b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan if (DEBUG) { 151b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan Log.e(TAG, "# Adding time zone from getAvailId: " + tzInfo.toString()); 152b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 153b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan mTimeZones.add(tzInfo); 154b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } else { 155b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan if (DEBUG) { 156b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan Log.e(TAG, 157b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan "# Dropping identical time zone from getAvailId: " + tzInfo.toString()); 158b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 159b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan continue; 160b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 161b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // 162b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // TODO check for dups 163b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // checkForNameDups(tz, tzInfo.mCountry, false /* dls */, 164b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // TimeZone.SHORT, groupIdx, !found); 165b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // checkForNameDups(tz, tzInfo.mCountry, false /* dls */, 166b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // TimeZone.LONG, groupIdx, !found); 167b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // if (tz.useDaylightTime()) { 168b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // checkForNameDups(tz, tzInfo.mCountry, true /* dls */, 169b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // TimeZone.SHORT, groupIdx, 170b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // !found); 171b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // checkForNameDups(tz, tzInfo.mCountry, true /* dls */, 172b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // TimeZone.LONG, groupIdx, 173b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // !found); 174b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // } 175b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 176b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 177b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // Don't change the order of mTimeZones after this sort 178b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan Collections.sort(mTimeZones); 179b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 180b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan mTimeZonesByCountry = new LinkedHashMap<String, ArrayList<Integer>>(); 181b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan mTimeZonesByOffsets = new SparseArray<ArrayList<Integer>>(mHasTimeZonesInHrOffset.length); 1821989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan mTimeZonesById = new HashMap<String, TimeZoneInfo>(mTimeZones.size()); 1831989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan for (TimeZoneInfo tz : mTimeZones) { 1841989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan // ///////////////////// 1851989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan // Lookup map for id -> tz 1861989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan mTimeZonesById.put(tz.mTzId, tz); 1871989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan } 1881989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan populateDisplayNameOverrides(mContext.getResources()); 189b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 190b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan Date date = new Date(mTimeMillis); 191b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan Locale defaultLocal = Locale.getDefault(); 192b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 193b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan int idx = 0; 194b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan for (TimeZoneInfo tz : mTimeZones) { 1951989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan // ///////////////////// 1961989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan // Populate display name 1971989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan if (tz.mDisplayName == null) { 1981989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan tz.mDisplayName = tz.mTz.getDisplayName(tz.mTz.inDaylightTime(date), 1991989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan TimeZone.LONG, defaultLocal); 2001989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan } 201b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 202b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // ///////////////////// 203b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // Grouping tz's by country for search by country 204b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan ArrayList<Integer> group = mTimeZonesByCountry.get(tz.mCountry); 205b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan if (group == null) { 206b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan group = new ArrayList<Integer>(); 207b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan mTimeZonesByCountry.put(tz.mCountry, group); 208b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 209b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 210b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan group.add(idx); 211b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 212b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // ///////////////////// 213b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // Grouping tz's by GMT offsets 214b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan indexByOffsets(idx, tz); 215b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 216b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // Skip all the GMT+xx:xx style display names from search 217b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan if (!tz.mDisplayName.endsWith(":00")) { 218b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan mTimeZoneNames.add(tz.mDisplayName); 219b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } else if (DEBUG) { 220b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan Log.e(TAG, "# Hiding from pretty name search: " + 221b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan tz.mDisplayName); 222b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 223b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 224b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan idx++; 225b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 2263d4445bb2a85048a735f21f7ec3ee9f9af6cee22Michael Chan 2273d4445bb2a85048a735f21f7ec3ee9f9af6cee22Michael Chan // printTimeZones(); 2283d4445bb2a85048a735f21f7ec3ee9f9af6cee22Michael Chan } 2293d4445bb2a85048a735f21f7ec3ee9f9af6cee22Michael Chan 2303d4445bb2a85048a735f21f7ec3ee9f9af6cee22Michael Chan private void printTimeZones() { 2313d4445bb2a85048a735f21f7ec3ee9f9af6cee22Michael Chan TimeZoneInfo last = null; 2323d4445bb2a85048a735f21f7ec3ee9f9af6cee22Michael Chan boolean first = true; 2333d4445bb2a85048a735f21f7ec3ee9f9af6cee22Michael Chan for (TimeZoneInfo tz : mTimeZones) { 2343d4445bb2a85048a735f21f7ec3ee9f9af6cee22Michael Chan // All 2353d4445bb2a85048a735f21f7ec3ee9f9af6cee22Michael Chan if (false) { 2363d4445bb2a85048a735f21f7ec3ee9f9af6cee22Michael Chan Log.e("ALL", tz.toString()); 2373d4445bb2a85048a735f21f7ec3ee9f9af6cee22Michael Chan } 2383d4445bb2a85048a735f21f7ec3ee9f9af6cee22Michael Chan 2393d4445bb2a85048a735f21f7ec3ee9f9af6cee22Michael Chan // GMT 2403d4445bb2a85048a735f21f7ec3ee9f9af6cee22Michael Chan if (true) { 2413d4445bb2a85048a735f21f7ec3ee9f9af6cee22Michael Chan String name = tz.mTz.getDisplayName(); 2423d4445bb2a85048a735f21f7ec3ee9f9af6cee22Michael Chan if (name.startsWith("GMT") && !tz.mTzId.startsWith("Etc/GMT")) { 2433d4445bb2a85048a735f21f7ec3ee9f9af6cee22Michael Chan Log.e("GMT", tz.toString()); 2443d4445bb2a85048a735f21f7ec3ee9f9af6cee22Michael Chan } 2453d4445bb2a85048a735f21f7ec3ee9f9af6cee22Michael Chan } 2463d4445bb2a85048a735f21f7ec3ee9f9af6cee22Michael Chan 2473d4445bb2a85048a735f21f7ec3ee9f9af6cee22Michael Chan // Dups 2483d4445bb2a85048a735f21f7ec3ee9f9af6cee22Michael Chan if (true && last != null) { 2493d4445bb2a85048a735f21f7ec3ee9f9af6cee22Michael Chan if (last.compareTo(tz) == 0) { 2503d4445bb2a85048a735f21f7ec3ee9f9af6cee22Michael Chan if (first) { 2513d4445bb2a85048a735f21f7ec3ee9f9af6cee22Michael Chan Log.e("SAME", last.toString()); 2523d4445bb2a85048a735f21f7ec3ee9f9af6cee22Michael Chan first = false; 2533d4445bb2a85048a735f21f7ec3ee9f9af6cee22Michael Chan } 2543d4445bb2a85048a735f21f7ec3ee9f9af6cee22Michael Chan Log.e("SAME", tz.toString()); 2553d4445bb2a85048a735f21f7ec3ee9f9af6cee22Michael Chan } else { 2563d4445bb2a85048a735f21f7ec3ee9f9af6cee22Michael Chan first = true; 2573d4445bb2a85048a735f21f7ec3ee9f9af6cee22Michael Chan } 2583d4445bb2a85048a735f21f7ec3ee9f9af6cee22Michael Chan } 2593d4445bb2a85048a735f21f7ec3ee9f9af6cee22Michael Chan last = tz; 2603d4445bb2a85048a735f21f7ec3ee9f9af6cee22Michael Chan } 2613d4445bb2a85048a735f21f7ec3ee9f9af6cee22Michael Chan Log.e(TAG, "Total number of tz's = " + mTimeZones.size()); 262b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 263b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 2641989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan private void populateDisplayNameOverrides(Resources resources) { 2651989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan String[] ids = resources.getStringArray(R.array.timezone_rename_ids); 2661989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan String[] labels = resources.getStringArray(R.array.timezone_rename_labels); 2671989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan 2681989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan int length = ids.length; 2691989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan if (ids.length != labels.length) { 2701989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan Log.e(TAG, "timezone_rename_ids len=" + ids.length + " timezone_rename_labels len=" 2711989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan + labels.length); 2721989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan length = Math.min(ids.length, labels.length); 2731989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan } 2741989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan 2751989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan for (int i = 0; i < length; i++) { 2761989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan TimeZoneInfo tzi = mTimeZonesById.get(ids[i]); 27796e8dde991e426d0cd44f5b4eb76118fd7374ac0Sam Blitzstein if (tzi != null) { 27896e8dde991e426d0cd44f5b4eb76118fd7374ac0Sam Blitzstein tzi.mDisplayName = labels[i]; 27996e8dde991e426d0cd44f5b4eb76118fd7374ac0Sam Blitzstein } else { 28096e8dde991e426d0cd44f5b4eb76118fd7374ac0Sam Blitzstein Log.e(TAG, "Could not find timezone with label: "+labels[i]); 28196e8dde991e426d0cd44f5b4eb76118fd7374ac0Sam Blitzstein } 2821989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan } 2831989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan } 284b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 285b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan public boolean hasTimeZonesInHrOffset(int offsetHr) { 286b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan int index = OFFSET_ARRAY_OFFSET + offsetHr; 287b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan if (index >= mHasTimeZonesInHrOffset.length || index < 0) { 288b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan return false; 289b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 290b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan return mHasTimeZonesInHrOffset[index]; 291b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 292b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 293b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan private void indexByOffsets(int idx, TimeZoneInfo tzi) { 294b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan int offsetMillis = tzi.getNowOffsetMillis(); 295b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan int index = OFFSET_ARRAY_OFFSET + (int) (offsetMillis / DateUtils.HOUR_IN_MILLIS); 296b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan mHasTimeZonesInHrOffset[index] = true; 297b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 298b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan ArrayList<Integer> group = mTimeZonesByOffsets.get(index); 299b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan if (group == null) { 300b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan group = new ArrayList<Integer>(); 301b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan mTimeZonesByOffsets.put(index, group); 302b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 303b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan group.add(idx); 304b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 305b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 306b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan public ArrayList<Integer> getTimeZonesByOffset(int offsetHr) { 307b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan int index = OFFSET_ARRAY_OFFSET + offsetHr; 308b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan if (index >= mHasTimeZonesInHrOffset.length || index < 0) { 309b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan return null; 310b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 311b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan return mTimeZonesByOffsets.get(index); 312b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 313b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 314b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan private HashSet<String> loadTzsInZoneTab(Context context) { 315b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan HashSet<String> processedTimeZones = new HashSet<String>(); 316b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan AssetManager am = context.getAssets(); 317b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan InputStream is = null; 318b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 319b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan /* 320b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan * The 'backward' file contain mappings between new and old time zone 321b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan * ids. We will explicitly ignore the old ones. 322b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan */ 323b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan try { 324b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan is = am.open("backward"); 325b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan BufferedReader reader = new BufferedReader(new InputStreamReader(is)); 326b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan String line; 327b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 328b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan while ((line = reader.readLine()) != null) { 329b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // Skip comment lines 330b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan if (!line.startsWith("#") && line.length() > 0) { 331b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // 0: "Link" 332b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // 1: New tz id 333b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // Last: Old tz id 334b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan String[] fields = line.split("\t+"); 335b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan String newTzId = fields[1]; 336b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan String oldTzId = fields[fields.length - 1]; 337b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 338b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan final TimeZone tz = TimeZone.getTimeZone(newTzId); 339b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan if (tz == null) { 340b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan Log.e(TAG, "Timezone not found: " + newTzId); 341b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan continue; 342b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 343b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 344b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan processedTimeZones.add(oldTzId); 345b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 346b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan if (DEBUG) { 347b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan Log.e(TAG, "# Dropping identical time zone from backward: " + oldTzId); 348b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 349b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 350b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // Remember the cooler/newer time zone id 351b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan if (mDefaultTimeZoneId != null && mDefaultTimeZoneId.equals(oldTzId)) { 352b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan mAlternateDefaultTimeZoneId = newTzId; 353b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 354b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 355b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 356b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } catch (IOException ex) { 357b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan Log.e(TAG, "Failed to read 'backward' file."); 358b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } finally { 359b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan try { 360b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan if (is != null) { 361b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan is.close(); 362b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 363b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } catch (IOException ignored) { 364b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 365b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 366b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 367b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan /* 368b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan * zone.tab contains a list of time zones and country code. They are 369b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan * "sorted first by country, then an order within the country that (1) 370b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan * makes some geographical sense, and (2) puts the most populous zones 371b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan * first, where that does not contradict (1)." 372b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan */ 373b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan try { 374b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan String lang = Locale.getDefault().getLanguage(); 375b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan is = am.open("zone.tab"); 376b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan BufferedReader reader = new BufferedReader(new InputStreamReader(is)); 377b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan String line; 378b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan while ((line = reader.readLine()) != null) { 379b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan if (!line.startsWith("#")) { // Skip comment lines 380b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // 0: country code 381b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // 1: coordinates 382b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // 2: time zone id 383b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // 3: comments 384b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan final String[] fields = line.split("\t"); 385b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan final String timeZoneId = fields[2]; 386b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan final String countryCode = fields[0]; 387b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan final TimeZone tz = TimeZone.getTimeZone(timeZoneId); 388b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan if (tz == null) { 389b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan Log.e(TAG, "Timezone not found: " + timeZoneId); 390b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan continue; 391b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 392b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 3931989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan /* 3941989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan * Dropping non-GMT tzs without a country code. They are not 3951989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan * really needed and they are dups but missing proper 3961989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan * country codes. e.g. WET CET MST7MDT PST8PDT Asia/Khandyga 3971989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan * Asia/Ust-Nera EST 3981989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan */ 3991989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan if (countryCode == null && !timeZoneId.startsWith("Etc/GMT")) { 4001989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan processedTimeZones.add(timeZoneId); 4011989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan continue; 4021989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan } 4031989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan 404b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // Remember the mapping between the country code and display 405b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // name 4061989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan String country = mCountryCodeToNameMap.get(countryCode); 407b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan if (country == null) { 408b506b1dddd4007997bbe6773cb0ebced27ba96dfMichael Chan country = getCountryNames(lang, countryCode); 409b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan mCountryCodeToNameMap.put(countryCode, country); 410b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 411b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 412b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // TODO Don't like this here but need to get the country of 413b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // the default tz. 414b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 415b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // Find the country of the default tz 416b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan if (mDefaultTimeZoneId != null && mDefaultTimeZoneCountry == null 417b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan && timeZoneId.equals(mAlternateDefaultTimeZoneId)) { 418b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan mDefaultTimeZoneCountry = country; 419b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan TimeZone defaultTz = TimeZone.getTimeZone(mDefaultTimeZoneId); 420b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan if (defaultTz != null) { 421b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan mDefaultTimeZoneInfo = new TimeZoneInfo(defaultTz, country); 422b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 423b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan int tzToOverride = getIdenticalTimeZoneInTheCountry(mDefaultTimeZoneInfo); 424b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan if (tzToOverride == -1) { 425b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan if (DEBUG) { 426b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan Log.e(TAG, "Adding default time zone: " 427b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan + mDefaultTimeZoneInfo.toString()); 428b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 429b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan mTimeZones.add(mDefaultTimeZoneInfo); 430b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } else { 431b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan mTimeZones.add(tzToOverride, mDefaultTimeZoneInfo); 432b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan if (DEBUG) { 433b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan TimeZoneInfo tzInfoToOverride = mTimeZones.get(tzToOverride); 434b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan String tzIdToOverride = tzInfoToOverride.mTzId; 435b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan Log.e(TAG, "Replaced by default tz: " 436b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan + tzInfoToOverride.toString()); 437b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan Log.e(TAG, "Adding default time zone: " 438b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan + mDefaultTimeZoneInfo.toString()); 439b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 440b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 441b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 442b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 443b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 444b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // Add to the list of time zones if the time zone is unique 445b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // in the given country. 446b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan TimeZoneInfo timeZoneInfo = new TimeZoneInfo(tz, country); 447b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan int identicalTzIdx = getIdenticalTimeZoneInTheCountry(timeZoneInfo); 448b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan if (identicalTzIdx == -1) { 449b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan if (DEBUG) { 450b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan Log.e(TAG, "# Adding time zone: " + timeZoneId + " ## " + 451b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan tz.getDisplayName()); 452b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 453b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan mTimeZones.add(timeZoneInfo); 454b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } else { 455b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan if (DEBUG) { 456b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan Log.e(TAG, "# Dropping identical time zone: " + timeZoneId + " ## " + 457b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan tz.getDisplayName()); 458b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 459b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 460b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan processedTimeZones.add(timeZoneId); 461b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 462b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 463b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 464b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } catch (IOException ex) { 465b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan Log.e(TAG, "Failed to read 'zone.tab'."); 466b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } finally { 467b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan try { 468b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan if (is != null) { 469b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan is.close(); 470b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 471b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } catch (IOException ignored) { 472b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 473b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 474b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 475b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan return processedTimeZones; 476b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 477b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 478b506b1dddd4007997bbe6773cb0ebced27ba96dfMichael Chan private static Locale mBackupCountryLocale; 479b506b1dddd4007997bbe6773cb0ebced27ba96dfMichael Chan private static String[] mBackupCountryCodes; 480b506b1dddd4007997bbe6773cb0ebced27ba96dfMichael Chan private static String[] mBackupCountryNames; 481b506b1dddd4007997bbe6773cb0ebced27ba96dfMichael Chan 482b506b1dddd4007997bbe6773cb0ebced27ba96dfMichael Chan private String getCountryNames(String lang, String countryCode) { 483b506b1dddd4007997bbe6773cb0ebced27ba96dfMichael Chan final Locale defaultLocale = Locale.getDefault(); 48462e91b1a6e5decfbe7206a381fed5ff9bb08785bSam Blitzstein String countryDisplayName; 48562e91b1a6e5decfbe7206a381fed5ff9bb08785bSam Blitzstein if (PALESTINE_COUNTRY_CODE.equalsIgnoreCase(countryCode)) { 48662e91b1a6e5decfbe7206a381fed5ff9bb08785bSam Blitzstein countryDisplayName = mPalestineDisplayName; 48762e91b1a6e5decfbe7206a381fed5ff9bb08785bSam Blitzstein } else { 48862e91b1a6e5decfbe7206a381fed5ff9bb08785bSam Blitzstein countryDisplayName = new Locale(lang, countryCode).getDisplayCountry(defaultLocale); 48962e91b1a6e5decfbe7206a381fed5ff9bb08785bSam Blitzstein } 490b506b1dddd4007997bbe6773cb0ebced27ba96dfMichael Chan 491b506b1dddd4007997bbe6773cb0ebced27ba96dfMichael Chan if (!countryCode.equals(countryDisplayName)) { 492b506b1dddd4007997bbe6773cb0ebced27ba96dfMichael Chan return countryDisplayName; 493b506b1dddd4007997bbe6773cb0ebced27ba96dfMichael Chan } 494b506b1dddd4007997bbe6773cb0ebced27ba96dfMichael Chan 495b506b1dddd4007997bbe6773cb0ebced27ba96dfMichael Chan if (mBackupCountryCodes == null || !defaultLocale.equals(mBackupCountryLocale)) { 496b506b1dddd4007997bbe6773cb0ebced27ba96dfMichael Chan mBackupCountryLocale = defaultLocale; 497b506b1dddd4007997bbe6773cb0ebced27ba96dfMichael Chan mBackupCountryCodes = mContext.getResources().getStringArray( 498b506b1dddd4007997bbe6773cb0ebced27ba96dfMichael Chan R.array.backup_country_codes); 499b506b1dddd4007997bbe6773cb0ebced27ba96dfMichael Chan mBackupCountryNames = mContext.getResources().getStringArray( 500b506b1dddd4007997bbe6773cb0ebced27ba96dfMichael Chan R.array.backup_country_names); 501b506b1dddd4007997bbe6773cb0ebced27ba96dfMichael Chan } 502b506b1dddd4007997bbe6773cb0ebced27ba96dfMichael Chan 503b506b1dddd4007997bbe6773cb0ebced27ba96dfMichael Chan int length = Math.min(mBackupCountryCodes.length, mBackupCountryNames.length); 504b506b1dddd4007997bbe6773cb0ebced27ba96dfMichael Chan 505b506b1dddd4007997bbe6773cb0ebced27ba96dfMichael Chan for (int i = 0; i < length; i++) { 506b506b1dddd4007997bbe6773cb0ebced27ba96dfMichael Chan if (mBackupCountryCodes[i].equals(countryCode)) { 507b506b1dddd4007997bbe6773cb0ebced27ba96dfMichael Chan return mBackupCountryNames[i]; 508b506b1dddd4007997bbe6773cb0ebced27ba96dfMichael Chan } 509b506b1dddd4007997bbe6773cb0ebced27ba96dfMichael Chan } 510b506b1dddd4007997bbe6773cb0ebced27ba96dfMichael Chan 511b506b1dddd4007997bbe6773cb0ebced27ba96dfMichael Chan return countryCode; 512b506b1dddd4007997bbe6773cb0ebced27ba96dfMichael Chan } 513b506b1dddd4007997bbe6773cb0ebced27ba96dfMichael Chan 514b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan private int getIdenticalTimeZoneInTheCountry(TimeZoneInfo timeZoneInfo) { 515b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan int idx = 0; 516b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan for (TimeZoneInfo tzi : mTimeZones) { 517b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan if (tzi.hasSameRules(timeZoneInfo)) { 518b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan if (tzi.mCountry == null) { 519b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan if (timeZoneInfo.mCountry == null) { 520b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan return idx; 521b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 522b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } else if (tzi.mCountry.equals(timeZoneInfo.mCountry)) { 523b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan return idx; 524b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 525b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 526b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan ++idx; 527b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 528b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan return -1; 529b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 530b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan} 531