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;
20143a7e20a46dbd66bec4e4d7e8e0dcb693d343d3Michael Chanimport android.text.Spannable;
21143a7e20a46dbd66bec4e4d7e8e0dcb693d343d3Michael Chanimport android.text.Spannable.Factory;
22b1b7080deea42aa533c3757b585cf765c6b76732Michael Chanimport android.text.format.DateUtils;
23b1b7080deea42aa533c3757b585cf765c6b76732Michael Chanimport android.text.format.Time;
24143a7e20a46dbd66bec4e4d7e8e0dcb693d343d3Michael Chanimport android.text.style.ForegroundColorSpan;
25b1b7080deea42aa533c3757b585cf765c6b76732Michael Chanimport android.util.Log;
26b1b7080deea42aa533c3757b585cf765c6b76732Michael Chanimport android.util.SparseArray;
27b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan
28b1b7080deea42aa533c3757b585cf765c6b76732Michael Chanimport java.lang.reflect.Field;
29b1b7080deea42aa533c3757b585cf765c6b76732Michael Chanimport java.text.DateFormat;
30b1b7080deea42aa533c3757b585cf765c6b76732Michael Chanimport java.util.Arrays;
31b1b7080deea42aa533c3757b585cf765c6b76732Michael Chanimport java.util.Date;
32b1b7080deea42aa533c3757b585cf765c6b76732Michael Chanimport java.util.Formatter;
33b1b7080deea42aa533c3757b585cf765c6b76732Michael Chanimport java.util.Locale;
34b1b7080deea42aa533c3757b585cf765c6b76732Michael Chanimport java.util.TimeZone;
35b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan
36b1b7080deea42aa533c3757b585cf765c6b76732Michael Chanpublic class TimeZoneInfo implements Comparable<TimeZoneInfo> {
37adbe2ac08b1456d2ed2e4adc2afa9c078a3e028eSam Blitzstein    private static final int GMT_TEXT_COLOR = TimeZonePickerUtils.GMT_TEXT_COLOR;
38adbe2ac08b1456d2ed2e4adc2afa9c078a3e028eSam Blitzstein    private static final int DST_SYMBOL_COLOR = TimeZonePickerUtils.DST_SYMBOL_COLOR;
39b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    private static final char SEPARATOR = ',';
40b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    private static final String TAG = null;
41b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    public static int NUM_OF_TRANSITIONS = 6;
42b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    public static long time = System.currentTimeMillis() / 1000;
43b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    public static boolean is24HourFormat;
44143a7e20a46dbd66bec4e4d7e8e0dcb693d343d3Michael Chan    private static final Factory mSpannableFactory = Spannable.Factory.getInstance();
45b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan
46b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    TimeZone mTz;
47b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    public String mTzId;
48b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    int mRawoffset;
49b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    public String mCountry;
50b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    public int groupId;
51b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    public String mDisplayName;
52b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    private Time recycledTime = new Time();
53b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    private static StringBuilder mSB = new StringBuilder(50);
54b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    private static Formatter mFormatter = new Formatter(mSB, Locale.getDefault());
55b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan
56b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    public TimeZoneInfo(TimeZone tz, String country) {
57b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        mTz = tz;
58b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        mTzId = tz.getID();
59b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        mCountry = country;
60b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        mRawoffset = tz.getRawOffset();
61b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    }
62b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan
63b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    SparseArray<String> mLocalTimeCache = new SparseArray<String>();
64b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    long mLocalTimeCacheReferenceTime = 0;
65b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    static private long mGmtDisplayNameUpdateTime;
66143a7e20a46dbd66bec4e4d7e8e0dcb693d343d3Michael Chan    static private SparseArray<CharSequence> mGmtDisplayNameCache =
67143a7e20a46dbd66bec4e4d7e8e0dcb693d343d3Michael Chan            new SparseArray<CharSequence>();
68b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan
69b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    public String getLocalTime(long referenceTime) {
70b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        recycledTime.timezone = TimeZone.getDefault().getID();
71b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        recycledTime.set(referenceTime);
72b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan
73b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        int currYearDay = recycledTime.year * 366 + recycledTime.yearDay;
74b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan
75b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        recycledTime.timezone = mTzId;
76b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        recycledTime.set(referenceTime);
77b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan
78b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        String localTimeStr = null;
79b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan
80b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        int hourMinute = recycledTime.hour * 60 +
81b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                recycledTime.minute;
82b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan
83b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        if (mLocalTimeCacheReferenceTime != referenceTime) {
84b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan            mLocalTimeCacheReferenceTime = referenceTime;
85b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan            mLocalTimeCache.clear();
86b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        } else {
87b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan            localTimeStr = mLocalTimeCache.get(hourMinute);
88b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        }
89b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan
90b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        if (localTimeStr == null) {
91b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan            String format = "%I:%M %p";
92b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan            if (currYearDay != (recycledTime.year * 366 + recycledTime.yearDay)) {
93b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                if (is24HourFormat) {
94b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                    format = "%b %d %H:%M";
95b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                } else {
96b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                    format = "%b %d %I:%M %p";
97b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                }
98b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan            } else if (is24HourFormat) {
99b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                format = "%H:%M";
100b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan            }
101b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan
102b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan            // format = "%Y-%m-%d %H:%M";
103b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan            localTimeStr = recycledTime.format(format);
104b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan            mLocalTimeCache.put(hourMinute, localTimeStr);
105b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        }
106b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan
107b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        return localTimeStr;
108b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    }
109b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan
110b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    public int getLocalHr(long referenceTime) {
1110717b65fee21de6a321e42c9f3852f8b622c3215Michael Chan        recycledTime.timezone = mTzId;
112b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        recycledTime.set(referenceTime);
113b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        return recycledTime.hour;
114b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    }
115b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan
116b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    public int getNowOffsetMillis() {
117b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        return mTz.getOffset(System.currentTimeMillis());
118b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    }
119b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan
120b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    /*
121b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan     * The method is synchronized because there's one mSB, which is used by
122b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan     * mFormatter, per instance. If there are multiple callers for
123b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan     * getGmtDisplayName, the output may be mangled.
124b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan     */
125143a7e20a46dbd66bec4e4d7e8e0dcb693d343d3Michael Chan    public synchronized CharSequence getGmtDisplayName(Context context) {
126b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        // TODO Note: The local time is shown in current time (current GMT
127b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        // offset) which may be different from the time specified by
128b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        // mTimeMillis
129b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan
130b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        final long nowMinute = System.currentTimeMillis() / DateUtils.MINUTE_IN_MILLIS;
131b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        final long now = nowMinute * DateUtils.MINUTE_IN_MILLIS;
132b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        final int gmtOffset = mTz.getOffset(now);
133b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        int cacheKey;
134b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan
135b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        boolean hasFutureDST = mTz.useDaylightTime();
136b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        if (hasFutureDST) {
137b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan            cacheKey = (int) (gmtOffset + 36 * DateUtils.HOUR_IN_MILLIS);
138b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        } else {
139b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan            cacheKey = (int) (gmtOffset - 36 * DateUtils.HOUR_IN_MILLIS);
140b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        }
141b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan
142143a7e20a46dbd66bec4e4d7e8e0dcb693d343d3Michael Chan        CharSequence displayName = null;
143b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        if (mGmtDisplayNameUpdateTime != nowMinute) {
144b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan            mGmtDisplayNameUpdateTime = nowMinute;
145b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan            mGmtDisplayNameCache.clear();
146b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        } else {
147b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan            displayName = mGmtDisplayNameCache.get(cacheKey);
148b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        }
149b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan
150b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        if (displayName == null) {
151b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan            mSB.setLength(0);
152b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan            int flags = DateUtils.FORMAT_ABBREV_ALL;
153b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan            flags |= DateUtils.FORMAT_SHOW_TIME;
154b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan            if (TimeZoneInfo.is24HourFormat) {
155b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                flags |= DateUtils.FORMAT_24HOUR;
156b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan            }
157b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan
158b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan            // mFormatter writes to mSB
159b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan            DateUtils.formatDateRange(context, mFormatter, now, now, flags, mTzId);
1605f2204bc83982ec4ffec0e01efa39325b4fe58aeSam Blitzstein            mSB.append("  ");
161adbe2ac08b1456d2ed2e4adc2afa9c078a3e028eSam Blitzstein            int gmtStart = mSB.length();
162143a7e20a46dbd66bec4e4d7e8e0dcb693d343d3Michael Chan            TimeZonePickerUtils.appendGmtOffset(mSB, gmtOffset);
163adbe2ac08b1456d2ed2e4adc2afa9c078a3e028eSam Blitzstein            int gmtEnd = mSB.length();
164b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan
165adbe2ac08b1456d2ed2e4adc2afa9c078a3e028eSam Blitzstein            int symbolStart = 0;
166adbe2ac08b1456d2ed2e4adc2afa9c078a3e028eSam Blitzstein            int symbolEnd = 0;
167b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan            if (hasFutureDST) {
168143a7e20a46dbd66bec4e4d7e8e0dcb693d343d3Michael Chan                mSB.append(' ');
169adbe2ac08b1456d2ed2e4adc2afa9c078a3e028eSam Blitzstein                symbolStart = mSB.length();
170143a7e20a46dbd66bec4e4d7e8e0dcb693d343d3Michael Chan                mSB.append(TimeZonePickerUtils.getDstSymbol()); // Sun symbol
171adbe2ac08b1456d2ed2e4adc2afa9c078a3e028eSam Blitzstein                symbolEnd = mSB.length();
172adbe2ac08b1456d2ed2e4adc2afa9c078a3e028eSam Blitzstein            }
173adbe2ac08b1456d2ed2e4adc2afa9c078a3e028eSam Blitzstein
174adbe2ac08b1456d2ed2e4adc2afa9c078a3e028eSam Blitzstein            // Set the gray colors.
175adbe2ac08b1456d2ed2e4adc2afa9c078a3e028eSam Blitzstein            Spannable spannableText = mSpannableFactory.newSpannable(mSB);
176adbe2ac08b1456d2ed2e4adc2afa9c078a3e028eSam Blitzstein            spannableText.setSpan(new ForegroundColorSpan(GMT_TEXT_COLOR),
177adbe2ac08b1456d2ed2e4adc2afa9c078a3e028eSam Blitzstein                    gmtStart, gmtEnd, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
178143a7e20a46dbd66bec4e4d7e8e0dcb693d343d3Michael Chan
179adbe2ac08b1456d2ed2e4adc2afa9c078a3e028eSam Blitzstein            if (hasFutureDST) {
180adbe2ac08b1456d2ed2e4adc2afa9c078a3e028eSam Blitzstein                spannableText.setSpan(new ForegroundColorSpan(DST_SYMBOL_COLOR),
181adbe2ac08b1456d2ed2e4adc2afa9c078a3e028eSam Blitzstein                        symbolStart, symbolEnd, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
182b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan            }
183adbe2ac08b1456d2ed2e4adc2afa9c078a3e028eSam Blitzstein            displayName = spannableText;
184b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan            mGmtDisplayNameCache.put(cacheKey, displayName);
185b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        }
186b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        return displayName;
187b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    }
188b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan
189b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    public boolean hasSameRules(TimeZoneInfo tzi) {
1903a54ae0f42d50e3b855139a3439f2965506c9c2aSam Blitzstein        return this.mTz.hasSameRules(tzi.mTz);
191b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    }
192b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan
193b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    @Override
194b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    public String toString() {
195b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        StringBuilder sb = new StringBuilder();
196b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan
197b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        final String country = this.mCountry;
198b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        final TimeZone tz = this.mTz;
199b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan
200b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        sb.append(mTzId);
201b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        sb.append(SEPARATOR);
202b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        sb.append(tz.getDisplayName(false /* daylightTime */, TimeZone.LONG));
203b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        sb.append(SEPARATOR);
204b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        sb.append(tz.getDisplayName(false /* daylightTime */, TimeZone.SHORT));
205b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        sb.append(SEPARATOR);
206b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        if (tz.useDaylightTime()) {
207b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan            sb.append(tz.getDisplayName(true, TimeZone.LONG));
208b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan            sb.append(SEPARATOR);
209b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan            sb.append(tz.getDisplayName(true, TimeZone.SHORT));
210b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        } else {
211b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan            sb.append(SEPARATOR);
212b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        }
213b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        sb.append(SEPARATOR);
214b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        sb.append(tz.getRawOffset() / 3600000f);
215b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        sb.append(SEPARATOR);
216b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        sb.append(tz.getDSTSavings() / 3600000f);
217b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        sb.append(SEPARATOR);
218b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        sb.append(country);
219b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        sb.append(SEPARATOR);
220b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan
221b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        // 1-1-2013 noon GMT
222b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        sb.append(getLocalTime(1357041600000L));
223b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        sb.append(SEPARATOR);
224b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan
225b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        // 3-15-2013 noon GMT
226b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        sb.append(getLocalTime(1363348800000L));
227b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        sb.append(SEPARATOR);
228b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan
229b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        // 7-1-2013 noon GMT
230b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        sb.append(getLocalTime(1372680000000L));
231b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        sb.append(SEPARATOR);
232b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan
233b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        // 11-01-2013 noon GMT
234b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        sb.append(getLocalTime(1383307200000L));
235b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        sb.append(SEPARATOR);
236b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan
237b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        sb.append('\n');
238b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        return sb.toString();
239b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    }
240b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan
241b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    private static String formatTime(DateFormat df, int s) {
242b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        long ms = s * 1000L;
243b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        return df.format(new Date(ms));
244b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    }
245b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan
246b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    /*
247b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan     * Returns a negative integer if this instance is less than the other; a
248b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan     * positive integer if this instance is greater than the other; 0 if this
249b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan     * instance has the same order as the other.
250b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan     */
251b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    @Override
252b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    public int compareTo(TimeZoneInfo other) {
2531989c63ae3f98b5088e27564cd397ef5e8affaeaMichael Chan        if (this.getNowOffsetMillis() != other.getNowOffsetMillis()) {
25409a2165919cb9b67c95b7885357c78e20bf5d9fbSam Blitzstein            return (other.getNowOffsetMillis() < this.getNowOffsetMillis()) ? -1 : 1;
255b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        }
256b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan
257b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        // By country
258b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        if (this.mCountry == null) {
259b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan            if (other.mCountry != null) {
260b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                return 1;
261b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan            }
262b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        }
263b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan
264b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        if (other.mCountry == null) {
265b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan            return -1;
266b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        } else {
267b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan            int diff = this.mCountry.compareTo(other.mCountry);
268b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan
269b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan            if (diff != 0) {
270b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                return diff;
271b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan            }
272b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        }
273b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan
274b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        // Finally diff by display name
2755e905dfdd9c374ddf708d19062501038211356d2Michael Chan        if (mDisplayName != null && other.mDisplayName != null)
2765e905dfdd9c374ddf708d19062501038211356d2Michael Chan            return this.mDisplayName.compareTo(other.mDisplayName);
2775e905dfdd9c374ddf708d19062501038211356d2Michael Chan
278b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan        return this.mTz.getDisplayName(Locale.getDefault()).compareTo(
279b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan                other.mTz.getDisplayName(Locale.getDefault()));
2805e905dfdd9c374ddf708d19062501038211356d2Michael Chan
281b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan    }
282b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan}
283