TimeZoneData.java revision 1989c63ae3f98b5088e27564cd397ef5e8affaea
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
45b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    ArrayList<TimeZoneInfo> mTimeZones;
46b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    LinkedHashMap<String, ArrayList<Integer>> mTimeZonesByCountry;
47b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    HashSet<String> mTimeZoneNames = new HashSet<String>();
48b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan
49b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    private long mTimeMillis;
50b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    private HashMap<String, String> mCountryCodeToNameMap = new HashMap<String, String>();
51b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan
52b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    public String mDefaultTimeZoneId;
53b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    public static boolean is24HourFormat;
54b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    private TimeZoneInfo mDefaultTimeZoneInfo;
55b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    private String mAlternateDefaultTimeZoneId;
56b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    private String mDefaultTimeZoneCountry;
571989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan    private HashMap<String, TimeZoneInfo> mTimeZonesById;
581989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan    private boolean[] mHasTimeZonesInHrOffset = new boolean[40];
591989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan    SparseArray<ArrayList<Integer>> mTimeZonesByOffsets;
601989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan    private Context mContext;
61b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan
62b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    public TimeZoneData(Context context, String defaultTimeZoneId, long timeMillis) {
631989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan        mContext = context;
64b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        is24HourFormat = TimeZoneInfo.is24HourFormat = DateFormat.is24HourFormat(context);
65b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        mDefaultTimeZoneId = mAlternateDefaultTimeZoneId = defaultTimeZoneId;
66b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        long now = System.currentTimeMillis();
67b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan
68b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        if (timeMillis == 0) {
69b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan            mTimeMillis = now;
70b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        } else {
71b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan            mTimeMillis = timeMillis;
72b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        }
73b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        loadTzs(context);
741989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan
75b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        Log.i(TAG, "Time to load time zones (ms): " + (System.currentTimeMillis() - now));
76b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan
77b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        // now = System.currentTimeMillis();
78b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        // printTz();
79b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        // Log.i(TAG, "Time to print time zones (ms): " +
80b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        // (System.currentTimeMillis() - now));
81b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    }
82b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan
83b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    public void setTime(long timeMillis) {
84b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        mTimeMillis = timeMillis;
85b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    }
86b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan
87b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    public TimeZoneInfo get(int position) {
88b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        return mTimeZones.get(position);
89b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    }
90b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan
91b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    public int size() {
92b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        return mTimeZones.size();
93b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    }
94b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan
95b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    public int getDefaultTimeZoneIndex() {
96b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        return mTimeZones.indexOf(mDefaultTimeZoneInfo);
97b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    }
98b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan
99b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    // TODO speed this up
100b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    public int findIndexByTimeZoneIdSlow(String timeZoneId) {
101b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        int idx = 0;
102b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        for (TimeZoneInfo tzi : mTimeZones) {
103b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan            if (timeZoneId.equals(tzi.mTzId)) {
104b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                return idx;
105b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan            }
106b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan            idx++;
107b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        }
108b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        return -1;
109b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    }
110b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan
111b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    void loadTzs(Context context) {
112b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        mTimeZones = new ArrayList<TimeZoneInfo>();
113b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        HashSet<String> processedTimeZones = loadTzsInZoneTab(context);
114b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        String[] tzIds = TimeZone.getAvailableIDs();
115b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan
116b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        if (DEBUG) {
117b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan            Log.e(TAG, "Available time zones: " + tzIds.length);
118b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        }
119b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan
120b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        for (String tzId : tzIds) {
121b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan            if (processedTimeZones.contains(tzId)) {
122b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                continue;
123b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan            }
124b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan
1251989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan            /*
1261989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan             * Dropping non-GMT tzs without a country code. They are not
1271989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan             * really needed and they are dups but missing proper
1281989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan             * country codes. e.g. WET CET MST7MDT PST8PDT Asia/Khandyga
1291989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan             * Asia/Ust-Nera EST
1301989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan             */
1311989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan            if (!tzId.startsWith("Etc/GMT")) {
1321989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan                continue;
1331989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan            }
1341989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan
135b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan            final TimeZone tz = TimeZone.getTimeZone(tzId);
136b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan            if (tz == null) {
137b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                Log.e(TAG, "Timezone not found: " + tzId);
138b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                continue;
139b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan            }
140b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan
141b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan            TimeZoneInfo tzInfo = new TimeZoneInfo(tz, null);
142b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan
143b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan            if (getIdenticalTimeZoneInTheCountry(tzInfo) == -1) {
144b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                if (DEBUG) {
145b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                    Log.e(TAG, "# Adding time zone from getAvailId: " + tzInfo.toString());
146b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                }
147b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                mTimeZones.add(tzInfo);
148b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan            } else {
149b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                if (DEBUG) {
150b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                    Log.e(TAG,
151b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                            "# Dropping identical time zone from getAvailId: " + tzInfo.toString());
152b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                }
153b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                continue;
154b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan            }
155b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan            //
156b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan            // TODO check for dups
157b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan            // checkForNameDups(tz, tzInfo.mCountry, false /* dls */,
158b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan            // TimeZone.SHORT, groupIdx, !found);
159b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan            // checkForNameDups(tz, tzInfo.mCountry, false /* dls */,
160b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan            // TimeZone.LONG, groupIdx, !found);
161b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan            // if (tz.useDaylightTime()) {
162b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan            // checkForNameDups(tz, tzInfo.mCountry, true /* dls */,
163b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan            // TimeZone.SHORT, groupIdx,
164b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan            // !found);
165b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan            // checkForNameDups(tz, tzInfo.mCountry, true /* dls */,
166b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan            // TimeZone.LONG, groupIdx,
167b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan            // !found);
168b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan            // }
169b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        }
170b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan
171b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        // Don't change the order of mTimeZones after this sort
172b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        Collections.sort(mTimeZones);
1731989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan        // TimeZoneInfo last = null;
1741989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan        // boolean first = true;
1751989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan        // for (TimeZoneInfo tz : mTimeZones) {
1761989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan        // // All
1771989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan        // Log.e("ALL", tz.toString());
1781989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan        //
1791989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan        // // GMT
1801989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan        // String name = tz.mTz.getDisplayName();
1811989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan        // if (name.startsWith("GMT") && !tz.mTzId.startsWith("Etc/GMT")) {
1821989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan        // Log.e("GMT", tz.toString());
1831989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan        // }
1841989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan        //
1851989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan        // // Dups
1861989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan        // if (last != null) {
1871989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan        // if (last.compareTo(tz) == 0) {
1881989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan        // if (first) {
1891989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan        // Log.e("SAME", last.toString());
1901989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan        // first = false;
1911989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan        // }
1921989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan        // Log.e("SAME", tz.toString());
1931989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan        // } else {
1941989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan        // first = true;
1951989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan        // }
1961989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan        // }
1971989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan        // last = tz;
1981989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan        // }
199b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan
200b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        mTimeZonesByCountry = new LinkedHashMap<String, ArrayList<Integer>>();
201b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        mTimeZonesByOffsets = new SparseArray<ArrayList<Integer>>(mHasTimeZonesInHrOffset.length);
2021989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan        mTimeZonesById = new HashMap<String, TimeZoneInfo>(mTimeZones.size());
2031989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan        for (TimeZoneInfo tz : mTimeZones) {
2041989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan            // /////////////////////
2051989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan            // Lookup map for id -> tz
2061989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan            mTimeZonesById.put(tz.mTzId, tz);
2071989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan        }
2081989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan        populateDisplayNameOverrides(mContext.getResources());
209b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan
210b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        Date date = new Date(mTimeMillis);
211b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        Locale defaultLocal = Locale.getDefault();
212b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan
213b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        int idx = 0;
214b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        for (TimeZoneInfo tz : mTimeZones) {
2151989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan            // /////////////////////
2161989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan            // Populate display name
2171989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan            if (tz.mDisplayName == null) {
2181989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan                tz.mDisplayName = tz.mTz.getDisplayName(tz.mTz.inDaylightTime(date),
2191989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan                        TimeZone.LONG, defaultLocal);
2201989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan            }
221b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan
222b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan            // /////////////////////
223b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan            // Grouping tz's by country for search by country
224b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan            ArrayList<Integer> group = mTimeZonesByCountry.get(tz.mCountry);
225b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan            if (group == null) {
226b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                group = new ArrayList<Integer>();
227b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                mTimeZonesByCountry.put(tz.mCountry, group);
228b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan            }
229b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan
230b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan            group.add(idx);
231b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan
232b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan            // /////////////////////
233b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan            // Grouping tz's by GMT offsets
234b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan            indexByOffsets(idx, tz);
235b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan
236b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan            // Skip all the GMT+xx:xx style display names from search
237b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan            if (!tz.mDisplayName.endsWith(":00")) {
238b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                mTimeZoneNames.add(tz.mDisplayName);
239b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan            } else if (DEBUG) {
240b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                Log.e(TAG, "# Hiding from pretty name search: " +
241b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                        tz.mDisplayName);
242b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan            }
243b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan
244b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan            idx++;
245b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        }
246b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    }
247b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan
2481989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan    private void populateDisplayNameOverrides(Resources resources) {
2491989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan        String[] ids = resources.getStringArray(R.array.timezone_rename_ids);
2501989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan        String[] labels = resources.getStringArray(R.array.timezone_rename_labels);
2511989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan
2521989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan        int length = ids.length;
2531989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan        if (ids.length != labels.length) {
2541989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan            Log.e(TAG, "timezone_rename_ids len=" + ids.length + " timezone_rename_labels len="
2551989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan                    + labels.length);
2561989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan            length = Math.min(ids.length, labels.length);
2571989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan        }
2581989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan
2591989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan        for (int i = 0; i < length; i++) {
2601989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan            TimeZoneInfo tzi = mTimeZonesById.get(ids[i]);
2611989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan            tzi.mDisplayName = labels[i];
2621989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan        }
2631989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan    }
264b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan
265b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    public boolean hasTimeZonesInHrOffset(int offsetHr) {
266b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        int index = OFFSET_ARRAY_OFFSET + offsetHr;
267b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        if (index >= mHasTimeZonesInHrOffset.length || index < 0) {
268b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan            return false;
269b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        }
270b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        return mHasTimeZonesInHrOffset[index];
271b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    }
272b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan
273b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    private void indexByOffsets(int idx, TimeZoneInfo tzi) {
274b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        int offsetMillis = tzi.getNowOffsetMillis();
275b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        int index = OFFSET_ARRAY_OFFSET + (int) (offsetMillis / DateUtils.HOUR_IN_MILLIS);
276b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        mHasTimeZonesInHrOffset[index] = true;
277b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan
278b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        ArrayList<Integer> group = mTimeZonesByOffsets.get(index);
279b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        if (group == null) {
280b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan            group = new ArrayList<Integer>();
281b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan            mTimeZonesByOffsets.put(index, group);
282b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        }
283b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        group.add(idx);
284b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    }
285b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan
286b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    public ArrayList<Integer> getTimeZonesByOffset(int offsetHr) {
287b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        int index = OFFSET_ARRAY_OFFSET + offsetHr;
288b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        if (index >= mHasTimeZonesInHrOffset.length || index < 0) {
289b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan            return null;
290b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        }
291b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        return mTimeZonesByOffsets.get(index);
292b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    }
293b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan
294b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    private HashSet<String> loadTzsInZoneTab(Context context) {
295b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        HashSet<String> processedTimeZones = new HashSet<String>();
296b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        AssetManager am = context.getAssets();
297b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        InputStream is = null;
298b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan
299b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        /*
300b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan         * The 'backward' file contain mappings between new and old time zone
301b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan         * ids. We will explicitly ignore the old ones.
302b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan         */
303b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        try {
304b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan            is = am.open("backward");
305b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan            BufferedReader reader = new BufferedReader(new InputStreamReader(is));
306b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan            String line;
307b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan
308b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan            while ((line = reader.readLine()) != null) {
309b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                // Skip comment lines
310b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                if (!line.startsWith("#") && line.length() > 0) {
311b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                    // 0: "Link"
312b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                    // 1: New tz id
313b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                    // Last: Old tz id
314b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                    String[] fields = line.split("\t+");
315b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                    String newTzId = fields[1];
316b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                    String oldTzId = fields[fields.length - 1];
317b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan
318b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                    final TimeZone tz = TimeZone.getTimeZone(newTzId);
319b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                    if (tz == null) {
320b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                        Log.e(TAG, "Timezone not found: " + newTzId);
321b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                        continue;
322b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                    }
323b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan
324b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                    processedTimeZones.add(oldTzId);
325b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan
326b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                    if (DEBUG) {
327b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                        Log.e(TAG, "# Dropping identical time zone from backward: " + oldTzId);
328b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                    }
329b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan
330b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                    // Remember the cooler/newer time zone id
331b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                    if (mDefaultTimeZoneId != null && mDefaultTimeZoneId.equals(oldTzId)) {
332b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                        mAlternateDefaultTimeZoneId = newTzId;
333b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                    }
334b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                }
335b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan            }
336b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        } catch (IOException ex) {
337b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan            Log.e(TAG, "Failed to read 'backward' file.");
338b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        } finally {
339b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan            try {
340b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                if (is != null) {
341b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                    is.close();
342b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                }
343b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan            } catch (IOException ignored) {
344b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan            }
345b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        }
346b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan
347b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        /*
348b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan         * zone.tab contains a list of time zones and country code. They are
349b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan         * "sorted first by country, then an order within the country that (1)
350b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan         * makes some geographical sense, and (2) puts the most populous zones
351b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan         * first, where that does not contradict (1)."
352b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan         */
353b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        try {
354b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan            String lang = Locale.getDefault().getLanguage();
355b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan            is = am.open("zone.tab");
356b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan            BufferedReader reader = new BufferedReader(new InputStreamReader(is));
357b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan            String line;
358b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan            while ((line = reader.readLine()) != null) {
359b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                if (!line.startsWith("#")) { // Skip comment lines
360b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                    // 0: country code
361b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                    // 1: coordinates
362b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                    // 2: time zone id
363b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                    // 3: comments
364b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                    final String[] fields = line.split("\t");
365b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                    final String timeZoneId = fields[2];
366b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                    final String countryCode = fields[0];
367b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                    final TimeZone tz = TimeZone.getTimeZone(timeZoneId);
368b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                    if (tz == null) {
369b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                        Log.e(TAG, "Timezone not found: " + timeZoneId);
370b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                        continue;
371b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                    }
372b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan
3731989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan                    /*
3741989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan                     * Dropping non-GMT tzs without a country code. They are not
3751989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan                     * really needed and they are dups but missing proper
3761989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan                     * country codes. e.g. WET CET MST7MDT PST8PDT Asia/Khandyga
3771989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan                     * Asia/Ust-Nera EST
3781989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan                     */
3791989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan                    if (countryCode == null && !timeZoneId.startsWith("Etc/GMT")) {
3801989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan                        processedTimeZones.add(timeZoneId);
3811989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan                        continue;
3821989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan                    }
3831989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan
384b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                    // Remember the mapping between the country code and display
385b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                    // name
3861989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan                    String country = mCountryCodeToNameMap.get(countryCode);
387b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                    if (country == null) {
388b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                        country = new Locale(lang, countryCode)
389b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                                .getDisplayCountry(Locale.getDefault());
390b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                        mCountryCodeToNameMap.put(countryCode, country);
391b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                    }
392b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan
393b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                    // TODO Don't like this here but need to get the country of
394b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                    // the default tz.
395b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan
396b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                    // Find the country of the default tz
397b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                    if (mDefaultTimeZoneId != null && mDefaultTimeZoneCountry == null
398b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                            && timeZoneId.equals(mAlternateDefaultTimeZoneId)) {
399b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                        mDefaultTimeZoneCountry = country;
400b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                        TimeZone defaultTz = TimeZone.getTimeZone(mDefaultTimeZoneId);
401b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                        if (defaultTz != null) {
402b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                            mDefaultTimeZoneInfo = new TimeZoneInfo(defaultTz, country);
403b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan
404b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                            int tzToOverride = getIdenticalTimeZoneInTheCountry(mDefaultTimeZoneInfo);
405b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                            if (tzToOverride == -1) {
406b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                                if (DEBUG) {
407b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                                    Log.e(TAG, "Adding default time zone: "
408b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                                            + mDefaultTimeZoneInfo.toString());
409b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                                }
410b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                                mTimeZones.add(mDefaultTimeZoneInfo);
411b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                            } else {
412b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                                mTimeZones.add(tzToOverride, mDefaultTimeZoneInfo);
413b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                                if (DEBUG) {
414b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                                    TimeZoneInfo tzInfoToOverride = mTimeZones.get(tzToOverride);
415b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                                    String tzIdToOverride = tzInfoToOverride.mTzId;
416b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                                    Log.e(TAG, "Replaced by default tz: "
417b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                                            + tzInfoToOverride.toString());
418b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                                    Log.e(TAG, "Adding default time zone: "
419b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                                            + mDefaultTimeZoneInfo.toString());
420b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                                }
421b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                            }
422b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                        }
423b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                    }
424b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan
425b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                    // Add to the list of time zones if the time zone is unique
426b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                    // in the given country.
427b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                    TimeZoneInfo timeZoneInfo = new TimeZoneInfo(tz, country);
428b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                    int identicalTzIdx = getIdenticalTimeZoneInTheCountry(timeZoneInfo);
429b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                    if (identicalTzIdx == -1) {
430b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                        if (DEBUG) {
431b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                            Log.e(TAG, "# Adding time zone: " + timeZoneId + " ## " +
432b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                                    tz.getDisplayName());
433b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                        }
434b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                        mTimeZones.add(timeZoneInfo);
435b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                    } else {
436b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                        if (DEBUG) {
437b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                            Log.e(TAG, "# Dropping identical time zone: " + timeZoneId + " ## " +
438b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                                    tz.getDisplayName());
439b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                        }
440b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                    }
441b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                    processedTimeZones.add(timeZoneId);
442b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                }
443b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan            }
444b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan
445b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        } catch (IOException ex) {
446b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan            Log.e(TAG, "Failed to read 'zone.tab'.");
447b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        } finally {
448b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan            try {
449b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                if (is != null) {
450b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                    is.close();
451b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                }
452b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan            } catch (IOException ignored) {
453b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan            }
454b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        }
455b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan
456b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        return processedTimeZones;
457b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    }
458b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan
459b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    private int getIdenticalTimeZoneInTheCountry(TimeZoneInfo timeZoneInfo) {
460b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        int idx = 0;
461b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        for (TimeZoneInfo tzi : mTimeZones) {
462b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan            if (tzi.hasSameRules(timeZoneInfo)) {
463b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                if (tzi.mCountry == null) {
464b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                    if (timeZoneInfo.mCountry == null) {
465b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                        return idx;
466b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                    }
467b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                } else if (tzi.mCountry.equals(timeZoneInfo.mCountry)) {
468b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                    return idx;
469b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                }
470b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan            }
471b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan            ++idx;
472b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        }
473b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        return -1;
474b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    }
475b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan
476b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    private void printTz() {
477b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        for (TimeZoneInfo tz : mTimeZones) {
478b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan            Log.e(TAG, "" + tz.toString());
479b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        }
480b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan
481b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        Log.e(TAG, "Total number of tz's = " + mTimeZones.size());
482b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    }
483b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan
484b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    // void checkForNameDups(TimeZone tz, String country, boolean dls, int
485b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    // style, int idx,
486b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    // boolean print) {
487b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    // if (country == null) {
488b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    // return;
489b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    // }
490b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    // String displayName = tz.getDisplayName(dls, style);
491b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    //
492b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    // if (print) {
493b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    // Log.e(TAG, "" + idx + " " + tz.getID() + " " + country + " ## " +
494b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    // displayName);
495b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    // }
496b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    //
497b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    // if (tz.useDaylightTime()) {
498b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    // if (displayName.matches("GMT[+-][0-9][0-9]:[0-9][0-9]")) {
499b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    // return;
500b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    // }
501b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    //
502b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    // if (displayName.length() == 3 && displayName.charAt(2) == 'T' &&
503b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    // (displayName.charAt(1) == 'S' || displayName.charAt(1) == 'D')) {
504b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    // displayName = "" + displayName.charAt(0) + 'T';
505b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    // } else {
506b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    // displayName = displayName.replace(" Daylight ",
507b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    // " ").replace(" Standard ", " ");
508b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    // }
509b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    // }
510b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    //
511b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    // String tzNameWithCountry = country + " ## " + displayName;
512b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    // Integer groupId = mCountryPlusTzName2Tzs.get(tzNameWithCountry);
513b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    // if (groupId == null) {
514b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    // mCountryPlusTzName2Tzs.put(tzNameWithCountry, idx);
515b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    // } else if (groupId != idx) {
516b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    // Log.e(TAG, "Yikes: " + tzNameWithCountry + " matches " + groupId +
517b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    // " and " + idx);
518b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    // }
519b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    // }
520b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan
521b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan}
522