• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2013 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.timezonepicker;
18 
19 import android.content.Context;
20 import android.text.Spannable;
21 import android.text.Spannable.Factory;
22 import android.text.format.DateUtils;
23 import android.text.format.Time;
24 import android.text.style.ForegroundColorSpan;
25 import android.util.Log;
26 import android.util.SparseArray;
27 
28 import java.lang.reflect.Field;
29 import java.text.DateFormat;
30 import java.util.Arrays;
31 import java.util.Date;
32 import java.util.Formatter;
33 import java.util.Locale;
34 import java.util.TimeZone;
35 
36 public class TimeZoneInfo implements Comparable<TimeZoneInfo> {
37     private static final int GMT_TEXT_COLOR = TimeZonePickerUtils.GMT_TEXT_COLOR;
38     private static final int DST_SYMBOL_COLOR = TimeZonePickerUtils.DST_SYMBOL_COLOR;
39     private static final char SEPARATOR = ',';
40     private static final String TAG = null;
41     public static int NUM_OF_TRANSITIONS = 6;
42     public static long time = System.currentTimeMillis() / 1000;
43     public static boolean is24HourFormat;
44     private static final Factory mSpannableFactory = Spannable.Factory.getInstance();
45 
46     TimeZone mTz;
47     public String mTzId;
48     int mRawoffset;
49     public String mCountry;
50     public int groupId;
51     public String mDisplayName;
52     private Time recycledTime = new Time();
53     private static StringBuilder mSB = new StringBuilder(50);
54     private static Formatter mFormatter = new Formatter(mSB, Locale.getDefault());
55 
TimeZoneInfo(TimeZone tz, String country)56     public TimeZoneInfo(TimeZone tz, String country) {
57         mTz = tz;
58         mTzId = tz.getID();
59         mCountry = country;
60         mRawoffset = tz.getRawOffset();
61     }
62 
63     SparseArray<String> mLocalTimeCache = new SparseArray<String>();
64     long mLocalTimeCacheReferenceTime = 0;
65     static private long mGmtDisplayNameUpdateTime;
66     static private SparseArray<CharSequence> mGmtDisplayNameCache =
67             new SparseArray<CharSequence>();
68 
getLocalTime(long referenceTime)69     public String getLocalTime(long referenceTime) {
70         recycledTime.timezone = TimeZone.getDefault().getID();
71         recycledTime.set(referenceTime);
72 
73         int currYearDay = recycledTime.year * 366 + recycledTime.yearDay;
74 
75         recycledTime.timezone = mTzId;
76         recycledTime.set(referenceTime);
77 
78         String localTimeStr = null;
79 
80         int hourMinute = recycledTime.hour * 60 +
81                 recycledTime.minute;
82 
83         if (mLocalTimeCacheReferenceTime != referenceTime) {
84             mLocalTimeCacheReferenceTime = referenceTime;
85             mLocalTimeCache.clear();
86         } else {
87             localTimeStr = mLocalTimeCache.get(hourMinute);
88         }
89 
90         if (localTimeStr == null) {
91             String format = "%I:%M %p";
92             if (currYearDay != (recycledTime.year * 366 + recycledTime.yearDay)) {
93                 if (is24HourFormat) {
94                     format = "%b %d %H:%M";
95                 } else {
96                     format = "%b %d %I:%M %p";
97                 }
98             } else if (is24HourFormat) {
99                 format = "%H:%M";
100             }
101 
102             // format = "%Y-%m-%d %H:%M";
103             localTimeStr = recycledTime.format(format);
104             mLocalTimeCache.put(hourMinute, localTimeStr);
105         }
106 
107         return localTimeStr;
108     }
109 
getLocalHr(long referenceTime)110     public int getLocalHr(long referenceTime) {
111         recycledTime.timezone = mTzId;
112         recycledTime.set(referenceTime);
113         return recycledTime.hour;
114     }
115 
getNowOffsetMillis()116     public int getNowOffsetMillis() {
117         return mTz.getOffset(System.currentTimeMillis());
118     }
119 
120     /*
121      * The method is synchronized because there's one mSB, which is used by
122      * mFormatter, per instance. If there are multiple callers for
123      * getGmtDisplayName, the output may be mangled.
124      */
getGmtDisplayName(Context context)125     public synchronized CharSequence getGmtDisplayName(Context context) {
126         // TODO Note: The local time is shown in current time (current GMT
127         // offset) which may be different from the time specified by
128         // mTimeMillis
129 
130         final long nowMinute = System.currentTimeMillis() / DateUtils.MINUTE_IN_MILLIS;
131         final long now = nowMinute * DateUtils.MINUTE_IN_MILLIS;
132         final int gmtOffset = mTz.getOffset(now);
133         int cacheKey;
134 
135         boolean hasFutureDST = mTz.useDaylightTime();
136         if (hasFutureDST) {
137             cacheKey = (int) (gmtOffset + 36 * DateUtils.HOUR_IN_MILLIS);
138         } else {
139             cacheKey = (int) (gmtOffset - 36 * DateUtils.HOUR_IN_MILLIS);
140         }
141 
142         CharSequence displayName = null;
143         if (mGmtDisplayNameUpdateTime != nowMinute) {
144             mGmtDisplayNameUpdateTime = nowMinute;
145             mGmtDisplayNameCache.clear();
146         } else {
147             displayName = mGmtDisplayNameCache.get(cacheKey);
148         }
149 
150         if (displayName == null) {
151             mSB.setLength(0);
152             int flags = DateUtils.FORMAT_ABBREV_ALL;
153             flags |= DateUtils.FORMAT_SHOW_TIME;
154             if (TimeZoneInfo.is24HourFormat) {
155                 flags |= DateUtils.FORMAT_24HOUR;
156             }
157 
158             // mFormatter writes to mSB
159             DateUtils.formatDateRange(context, mFormatter, now, now, flags, mTzId);
160             mSB.append("  ");
161             int gmtStart = mSB.length();
162             TimeZonePickerUtils.appendGmtOffset(mSB, gmtOffset);
163             int gmtEnd = mSB.length();
164 
165             int symbolStart = 0;
166             int symbolEnd = 0;
167             if (hasFutureDST) {
168                 mSB.append(' ');
169                 symbolStart = mSB.length();
170                 mSB.append(TimeZonePickerUtils.getDstSymbol()); // Sun symbol
171                 symbolEnd = mSB.length();
172             }
173 
174             // Set the gray colors.
175             Spannable spannableText = mSpannableFactory.newSpannable(mSB);
176             spannableText.setSpan(new ForegroundColorSpan(GMT_TEXT_COLOR),
177                     gmtStart, gmtEnd, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
178 
179             if (hasFutureDST) {
180                 spannableText.setSpan(new ForegroundColorSpan(DST_SYMBOL_COLOR),
181                         symbolStart, symbolEnd, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
182             }
183             displayName = spannableText;
184             mGmtDisplayNameCache.put(cacheKey, displayName);
185         }
186         return displayName;
187     }
188 
hasSameRules(TimeZoneInfo tzi)189     public boolean hasSameRules(TimeZoneInfo tzi) {
190         return this.mTz.hasSameRules(tzi.mTz);
191     }
192 
193     @Override
toString()194     public String toString() {
195         StringBuilder sb = new StringBuilder();
196 
197         final String country = this.mCountry;
198         final TimeZone tz = this.mTz;
199 
200         sb.append(mTzId);
201         sb.append(SEPARATOR);
202         sb.append(tz.getDisplayName(false /* daylightTime */, TimeZone.LONG));
203         sb.append(SEPARATOR);
204         sb.append(tz.getDisplayName(false /* daylightTime */, TimeZone.SHORT));
205         sb.append(SEPARATOR);
206         if (tz.useDaylightTime()) {
207             sb.append(tz.getDisplayName(true, TimeZone.LONG));
208             sb.append(SEPARATOR);
209             sb.append(tz.getDisplayName(true, TimeZone.SHORT));
210         } else {
211             sb.append(SEPARATOR);
212         }
213         sb.append(SEPARATOR);
214         sb.append(tz.getRawOffset() / 3600000f);
215         sb.append(SEPARATOR);
216         sb.append(tz.getDSTSavings() / 3600000f);
217         sb.append(SEPARATOR);
218         sb.append(country);
219         sb.append(SEPARATOR);
220 
221         // 1-1-2013 noon GMT
222         sb.append(getLocalTime(1357041600000L));
223         sb.append(SEPARATOR);
224 
225         // 3-15-2013 noon GMT
226         sb.append(getLocalTime(1363348800000L));
227         sb.append(SEPARATOR);
228 
229         // 7-1-2013 noon GMT
230         sb.append(getLocalTime(1372680000000L));
231         sb.append(SEPARATOR);
232 
233         // 11-01-2013 noon GMT
234         sb.append(getLocalTime(1383307200000L));
235         sb.append(SEPARATOR);
236 
237         sb.append('\n');
238         return sb.toString();
239     }
240 
formatTime(DateFormat df, int s)241     private static String formatTime(DateFormat df, int s) {
242         long ms = s * 1000L;
243         return df.format(new Date(ms));
244     }
245 
246     /*
247      * Returns a negative integer if this instance is less than the other; a
248      * positive integer if this instance is greater than the other; 0 if this
249      * instance has the same order as the other.
250      */
251     @Override
compareTo(TimeZoneInfo other)252     public int compareTo(TimeZoneInfo other) {
253         if (this.getNowOffsetMillis() != other.getNowOffsetMillis()) {
254             return (other.getNowOffsetMillis() < this.getNowOffsetMillis()) ? -1 : 1;
255         }
256 
257         // By country
258         if (this.mCountry == null) {
259             if (other.mCountry != null) {
260                 return 1;
261             }
262         }
263 
264         if (other.mCountry == null) {
265             return -1;
266         } else {
267             int diff = this.mCountry.compareTo(other.mCountry);
268 
269             if (diff != 0) {
270                 return diff;
271             }
272         }
273 
274         // Finally diff by display name
275         if (mDisplayName != null && other.mDisplayName != null)
276             return this.mDisplayName.compareTo(other.mDisplayName);
277 
278         return this.mTz.getDisplayName(Locale.getDefault()).compareTo(
279                 other.mTz.getDisplayName(Locale.getDefault()));
280 
281     }
282 }
283