TimeZonePickerUtils.java revision 099b3306d12e24f8f7e76a140c69791739fe6ed0
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 17package com.android.timezonepicker; 18 19import android.content.Context; 20import android.content.res.Resources; 21import android.os.Build; 22import android.text.format.DateUtils; 23import android.text.format.Time; 24import android.util.Log; 25 26import java.util.Locale; 27import java.util.TimeZone; 28 29public class TimeZonePickerUtils { 30 private static final String TAG = "TimeZonePickerUtils"; 31 32 private Locale mDefaultLocale; 33 private String[] mOverrideIds; 34 private String[] mOverrideLabels; 35 36 /** 37 * This needs to be an instantiated class so that it doesn't need to continuously re-load the 38 * list of timezone IDs that need to be overridden. 39 * @param context 40 */ 41 public TimeZonePickerUtils(Context context) { 42 // Instead of saving a reference to the context (because we might need to look up the 43 // labels every time getGmtDisplayName is called), we'll cache the lists of override IDs 44 // and labels now. 45 cacheOverrides(context); 46 } 47 48 /** 49 * Given a timezone id (e.g. America/Los_Angeles), returns the corresponding timezone 50 * display name (e.g. (GMT-7.00) Pacific Time). 51 * 52 * @param context Context in case the override labels need to be re-cached. 53 * @param id The timezone id 54 * @param millis The time (daylight savings or not) 55 * @return The display name of the timezone. 56 */ 57 public String getGmtDisplayName(Context context, String id, long millis) { 58 TimeZone timezone = TimeZone.getTimeZone(id); 59 if (timezone == null) { 60 return null; 61 } 62 63 final Locale defaultLocale = Locale.getDefault(); 64 if (!defaultLocale.equals(mDefaultLocale)) { 65 // If the IDs and labels haven't been set yet, or if the locale has been changed 66 // recently, we'll need to re-cache them. 67 mDefaultLocale = defaultLocale; 68 cacheOverrides(context); 69 } 70 return buildGmtDisplayName(timezone, millis); 71 } 72 73 private String buildGmtDisplayName(TimeZone tz, long timeMillis) { 74 Time time = new Time(tz.getID()); 75 time.set(timeMillis); 76 77 StringBuilder sb = new StringBuilder(); 78 sb.append("(GMT"); 79 80 final int gmtOffset = tz.getOffset(timeMillis); 81 if (gmtOffset < 0) { 82 sb.append('-'); 83 } else { 84 sb.append('+'); 85 } 86 87 final int p = Math.abs(gmtOffset); 88 sb.append(p / DateUtils.HOUR_IN_MILLIS); // Hour 89 90 final int min = (p / (int) DateUtils.MINUTE_IN_MILLIS) % 60; 91 if (min != 0) { // Show minutes if non-zero 92 sb.append(':'); 93 if (min < 10) { 94 sb.append('0'); 95 } 96 sb.append(min); 97 } 98 sb.append(") "); 99 100 String displayName = getDisplayName(tz, time.isDst != 0); 101 sb.append(displayName); 102 103 if (tz.useDaylightTime()) { 104 String dstSymbol = getDstSymbol(); 105 sb.append(" "); 106 sb.append(dstSymbol); // Sun symbol 107 } 108 return sb.toString(); 109 } 110 111 public static String getDstSymbol() { 112 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { 113 return "\u2600"; // The Sun emoji icon. 114 } else { 115 return "*"; 116 } 117 } 118 119 /** 120 * Gets the display name for the specified Timezone ID. If the ID matches the list of IDs that 121 * need to be have their default display names overriden, use the pre-set display name from 122 * R.arrays. 123 * @param id The timezone ID. 124 * @param daylightTime True for daylight time, false for standard time 125 * @return The display name of the timezone. This will just use the default display name, 126 * except that certain timezones have poor defaults, and should use the pre-set override labels 127 * from R.arrays. 128 */ 129 private String getDisplayName(TimeZone tz, boolean daylightTime) { 130 if (mOverrideIds == null || mOverrideLabels == null) { 131 // Just in case they somehow didn't get loaded correctly. 132 return tz.getDisplayName(daylightTime, TimeZone.LONG, Locale.getDefault()); 133 } 134 135 for (int i = 0; i < mOverrideIds.length; i++) { 136 if (tz.getID().equals(mOverrideIds[i])) { 137 if (mOverrideLabels.length > i) { 138 return mOverrideLabels[i]; 139 } 140 Log.e(TAG, "timezone_rename_ids len=" + mOverrideIds.length + 141 " timezone_rename_labels len=" + mOverrideLabels.length); 142 break; 143 } 144 } 145 146 // If the ID doesn't need to have the display name overridden, or if the labels were 147 // malformed, just use the default. 148 return tz.getDisplayName(daylightTime, TimeZone.LONG, Locale.getDefault()); 149 } 150 151 private void cacheOverrides(Context context) { 152 Resources res = context.getResources(); 153 mOverrideIds = res.getStringArray(R.array.timezone_rename_ids); 154 mOverrideLabels = res.getStringArray(R.array.timezone_rename_labels); 155 } 156} 157