TimeZoneInfo.java revision b1b7080deea42aa533c3757b585cf765c6b76732
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.text.format.DateUtils; 21b1b7080deea42aa533c3757b585cf765c6b76732Michael Chanimport android.text.format.Time; 22b1b7080deea42aa533c3757b585cf765c6b76732Michael Chanimport android.util.Log; 23b1b7080deea42aa533c3757b585cf765c6b76732Michael Chanimport android.util.SparseArray; 24b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 25b1b7080deea42aa533c3757b585cf765c6b76732Michael Chanimport java.lang.reflect.Field; 26b1b7080deea42aa533c3757b585cf765c6b76732Michael Chanimport java.text.DateFormat; 27b1b7080deea42aa533c3757b585cf765c6b76732Michael Chanimport java.util.Arrays; 28b1b7080deea42aa533c3757b585cf765c6b76732Michael Chanimport java.util.Date; 29b1b7080deea42aa533c3757b585cf765c6b76732Michael Chanimport java.util.Formatter; 30b1b7080deea42aa533c3757b585cf765c6b76732Michael Chanimport java.util.Locale; 31b1b7080deea42aa533c3757b585cf765c6b76732Michael Chanimport java.util.TimeZone; 32b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 33b1b7080deea42aa533c3757b585cf765c6b76732Michael Chanpublic class TimeZoneInfo implements Comparable<TimeZoneInfo> { 34b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan private static final char SEPARATOR = ','; 35b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan private static final String TAG = null; 36b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan public static int NUM_OF_TRANSITIONS = 6; 37b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan public static long time = System.currentTimeMillis() / 1000; 38b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan public static boolean is24HourFormat; 39b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 40b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan TimeZone mTz; 41b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan public String mTzId; 42b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan int mRawoffset; 43b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan public int[] mTransitions; // may have trailing 0's. 44b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan public String mCountry; 45b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan public int groupId; 46b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan private boolean hasDst; 47b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan public String mDisplayName; 48b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan private Time recycledTime = new Time(); 49b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan private static StringBuilder mSB = new StringBuilder(50); 50b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan private static Formatter mFormatter = new Formatter(mSB, Locale.getDefault()); 51b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 52b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan public TimeZoneInfo(TimeZone tz, String country) { 53b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan mTz = tz; 54b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan mTzId = tz.getID(); 55b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan mCountry = country; 56b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan mRawoffset = tz.getRawOffset(); 57b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan hasDst = tz.useDaylightTime(); 58b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 59b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan try { 60b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan mTransitions = getTransitions(tz, time); 61b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } catch (NoSuchFieldException ignored) { 62b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } catch (IllegalAccessException ignored) { 63b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan ignored.printStackTrace(); 64b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 65b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 66b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 67b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan SparseArray<String> mLocalTimeCache = new SparseArray<String>(); 68b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan long mLocalTimeCacheReferenceTime = 0; 69b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan static private long mGmtDisplayNameUpdateTime; 70b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan static private SparseArray<String> mGmtDisplayNameCache = new SparseArray<String>(); 71b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 72b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan public String getLocalTime(long referenceTime) { 73b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan recycledTime.timezone = TimeZone.getDefault().getID(); 74b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan recycledTime.set(referenceTime); 75b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 76b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan int currYearDay = recycledTime.year * 366 + recycledTime.yearDay; 77b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 78b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan recycledTime.timezone = mTzId; 79b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan recycledTime.set(referenceTime); 80b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 81b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan String localTimeStr = null; 82b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 83b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan int hourMinute = recycledTime.hour * 60 + 84b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan recycledTime.minute; 85b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 86b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan if (mLocalTimeCacheReferenceTime != referenceTime) { 87b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan mLocalTimeCacheReferenceTime = referenceTime; 88b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan mLocalTimeCache.clear(); 89b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } else { 90b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan localTimeStr = mLocalTimeCache.get(hourMinute); 91b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 92b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 93b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan if (localTimeStr == null) { 94b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan String format = "%I:%M %p"; 95b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan if (currYearDay != (recycledTime.year * 366 + recycledTime.yearDay)) { 96b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan if (is24HourFormat) { 97b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan format = "%b %d %H:%M"; 98b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } else { 99b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan format = "%b %d %I:%M %p"; 100b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 101b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } else if (is24HourFormat) { 102b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan format = "%H:%M"; 103b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 104b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 105b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // format = "%Y-%m-%d %H:%M"; 106b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan localTimeStr = recycledTime.format(format); 107b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan mLocalTimeCache.put(hourMinute, localTimeStr); 108b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 109b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 110b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan return localTimeStr; 111b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 112b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 113b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan public int getLocalHr(long referenceTime) { 114b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan recycledTime.timezone = TimeZone.getDefault().getID(); 115b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan recycledTime.set(referenceTime); 116b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan return recycledTime.hour; 117b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 118b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 119b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan public int getNowOffsetMillis() { 120b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan return mTz.getOffset(System.currentTimeMillis()); 121b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 122b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 123b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan /* 124b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan * The method is synchronized because there's one mSB, which is used by 125b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan * mFormatter, per instance. If there are multiple callers for 126b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan * getGmtDisplayName, the output may be mangled. 127b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan */ 128b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan public synchronized String getGmtDisplayName(Context context) { 129b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // TODO Note: The local time is shown in current time (current GMT 130b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // offset) which may be different from the time specified by 131b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // mTimeMillis 132b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 133b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan final long nowMinute = System.currentTimeMillis() / DateUtils.MINUTE_IN_MILLIS; 134b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan final long now = nowMinute * DateUtils.MINUTE_IN_MILLIS; 135b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan final int gmtOffset = mTz.getOffset(now); 136b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan int cacheKey; 137b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 138b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan boolean hasFutureDST = mTz.useDaylightTime(); 139b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan if (hasFutureDST) { 140b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan cacheKey = (int) (gmtOffset + 36 * DateUtils.HOUR_IN_MILLIS); 141b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } else { 142b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan cacheKey = (int) (gmtOffset - 36 * DateUtils.HOUR_IN_MILLIS); 143b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 144b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 145b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan String displayName = null; 146b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan if (mGmtDisplayNameUpdateTime != nowMinute) { 147b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan mGmtDisplayNameUpdateTime = nowMinute; 148b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan mGmtDisplayNameCache.clear(); 149b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } else { 150b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan displayName = mGmtDisplayNameCache.get(cacheKey); 151b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 152b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 153b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan if (displayName == null) { 154b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan mSB.setLength(0); 155b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan int flags = DateUtils.FORMAT_ABBREV_ALL; 156b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan flags |= DateUtils.FORMAT_SHOW_TIME; 157b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan if (TimeZoneInfo.is24HourFormat) { 158b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan flags |= DateUtils.FORMAT_24HOUR; 159b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 160b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 161b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // mFormatter writes to mSB 162b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan DateUtils.formatDateRange(context, mFormatter, now, now, flags, mTzId); 163b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan mSB.append(" (GMT"); 164b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 165b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan if (gmtOffset < 0) { 166b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan mSB.append('-'); 167b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } else { 168b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan mSB.append('+'); 169b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 170b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 171b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan final int p = Math.abs(gmtOffset); 172b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan mSB.append(p / DateUtils.HOUR_IN_MILLIS); // Hour 173b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 174b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan final int min = (p / 60000) % 60; 175b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan if (min != 0) { // Show minutes if non-zero 176b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan mSB.append(':'); 177b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan if (min < 10) { 178b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan mSB.append('0'); 179b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 180b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan mSB.append(min); 181b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 182b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan mSB.append(')'); 183b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 184b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan if (hasFutureDST) { 185b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan mSB.append(" \u2600"); // Sun symbol 186b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 187b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 188b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan displayName = mSB.toString(); 189b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan mGmtDisplayNameCache.put(cacheKey, displayName); 190b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 191b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan return displayName; 192b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 193b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 194b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan private static int[] getTransitions(TimeZone tz, long time) 195b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan throws IllegalAccessException, NoSuchFieldException { 196b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan Class<?> zoneInfoClass = tz.getClass(); 197b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan Field mTransitionsField = zoneInfoClass.getDeclaredField("mTransitions"); 198b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan mTransitionsField.setAccessible(true); 199b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan int[] objTransitions = (int[]) mTransitionsField.get(tz); 200b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan int[] transitions = null; 201b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan if (objTransitions.length != 0) { 202b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan transitions = new int[NUM_OF_TRANSITIONS]; 203b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan int numOfTransitions = 0; 204b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan for (int i = 0; i < objTransitions.length; ++i) { 205b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan if (objTransitions[i] < time) { 206b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan continue; 207b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 208b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan transitions[numOfTransitions++] = objTransitions[i]; 209b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan if (numOfTransitions == NUM_OF_TRANSITIONS) { 210b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan break; 211b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 212b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 213b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 214b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan return transitions; 215b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 216b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 217b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan public boolean hasSameRules(TimeZoneInfo tzi) { 218b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // this.mTz.hasSameRules(tzi.mTz) 219b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 220b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan return this.mRawoffset == tzi.mRawoffset 221b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan && Arrays.equals(this.mTransitions, tzi.mTransitions); 222b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 223b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 224b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan @Override 225b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan public String toString() { 226b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan StringBuilder sb = new StringBuilder(); 227b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 228b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan final String country = this.mCountry; 229b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan final TimeZone tz = this.mTz; 230b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 231b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan sb.append(mTzId); 232b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan sb.append(SEPARATOR); 233b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan sb.append(tz.getDisplayName(false /* daylightTime */, TimeZone.LONG)); 234b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan sb.append(SEPARATOR); 235b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan sb.append(tz.getDisplayName(false /* daylightTime */, TimeZone.SHORT)); 236b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan sb.append(SEPARATOR); 237b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan if (tz.useDaylightTime()) { 238b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan sb.append(tz.getDisplayName(true, TimeZone.LONG)); 239b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan sb.append(SEPARATOR); 240b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan sb.append(tz.getDisplayName(true, TimeZone.SHORT)); 241b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } else { 242b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan sb.append(SEPARATOR); 243b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 244b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan sb.append(SEPARATOR); 245b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan sb.append(tz.getRawOffset() / 3600000f); 246b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan sb.append(SEPARATOR); 247b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan sb.append(tz.getDSTSavings() / 3600000f); 248b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan sb.append(SEPARATOR); 249b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan sb.append(country); 250b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan sb.append(SEPARATOR); 251b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 252b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // 1-1-2013 noon GMT 253b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan sb.append(getLocalTime(1357041600000L)); 254b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan sb.append(SEPARATOR); 255b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 256b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // 3-15-2013 noon GMT 257b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan sb.append(getLocalTime(1363348800000L)); 258b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan sb.append(SEPARATOR); 259b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 260b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // 7-1-2013 noon GMT 261b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan sb.append(getLocalTime(1372680000000L)); 262b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan sb.append(SEPARATOR); 263b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 264b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // 11-01-2013 noon GMT 265b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan sb.append(getLocalTime(1383307200000L)); 266b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan sb.append(SEPARATOR); 267b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 268b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // if (this.mTransitions != null && this.mTransitions.length != 0) { 269b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // sb.append('"'); 270b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // DateFormat df = new SimpleDateFormat("yyyy-MM-dd' 'HH:mm:ss Z", 271b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // Locale.US); 272b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // df.setTimeZone(tz); 273b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // DateFormat weekdayFormat = new SimpleDateFormat("EEEE", Locale.US); 274b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // weekdayFormat.setTimeZone(tz); 275b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // Formatter f = new Formatter(sb); 276b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // for (int i = 0; i < this.mTransitions.length; ++i) { 277b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // if (this.mTransitions[i] < time) { 278b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // continue; 279b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // } 280b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // 281b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // String fromTime = formatTime(df, this.mTransitions[i] - 1); 282b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // String toTime = formatTime(df, this.mTransitions[i]); 283b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // f.format("%s -> %s (%d)", fromTime, toTime, this.mTransitions[i]); 284b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // 285b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // String weekday = weekdayFormat.format(new Date(1000L * 286b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // this.mTransitions[i])); 287b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // if (!weekday.equals("Sunday")) { 288b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // f.format(" -- %s", weekday); 289b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // } 290b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // sb.append("##"); 291b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // } 292b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // sb.append('"'); 293b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // } 294b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // sb.append(SEPARATOR); 295b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan sb.append('\n'); 296b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan return sb.toString(); 297b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 298b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 299b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan private static String formatTime(DateFormat df, int s) { 300b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan long ms = s * 1000L; 301b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan return df.format(new Date(ms)); 302b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 303b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 304b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan /* 305b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan * Returns a negative integer if this instance is less than the other; a 306b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan * positive integer if this instance is greater than the other; 0 if this 307b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan * instance has the same order as the other. 308b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan */ 309b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan @Override 310b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan public int compareTo(TimeZoneInfo other) { 311b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 312b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // TODO !!! Should compare the clock time instead of raw offset 313b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 314b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // Higher raw offset comes before i.e. if the offset is bigger, return 315b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // positive number. 316b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan if (this.mRawoffset != other.mRawoffset) { 317b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan return other.mRawoffset - this.mRawoffset; 318b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 319b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 320b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // TZ with DST comes first because the offset is bigger during DST 321b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // compared to a tz without DST 322b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan if (this.hasDst != other.hasDst) { 323b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan return this.hasDst ? -1 : 1; 324b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 325b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 326b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // By country 327b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan if (this.mCountry == null) { 328b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan if (other.mCountry != null) { 329b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan return 1; 330b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 331b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 332b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 333b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan if (other.mCountry == null) { 334b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan return -1; 335b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } else { 336b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan int diff = this.mCountry.compareTo(other.mCountry); 337b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 338b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan if (diff != 0) { 339b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan return diff; 340b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 341b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 342b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 343b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan if (Arrays.equals(this.mTransitions, other.mTransitions)) { 344b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan Log.e(TAG, "Not expected to be comparing tz with the same country, same offset," + 345b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan " same dst, same transitions:\n" + this.toString() + "\n" + other.toString()); 346b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 347b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 348b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // Finally diff by display name 349b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan return this.mTz.getDisplayName(Locale.getDefault()).compareTo( 350b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan other.mTz.getDisplayName(Locale.getDefault())); 351b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 352b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan} 353