1 /*
2  * Copyright (C) 2017 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 package com.android.settings.datetime.timezone;
17 
18 import static com.android.settingslib.datetime.ZoneGetter.capitalizeForStandaloneDisplay;
19 
20 import android.icu.text.TimeZoneFormat;
21 import android.icu.text.TimeZoneNames;
22 import android.icu.util.TimeZone;
23 import android.text.TextUtils;
24 
25 import com.android.settingslib.datetime.ZoneGetter;
26 
27 import java.util.Date;
28 import java.util.Locale;
29 
30 /**
31  * Data object containing information for displaying a time zone for the user to select.
32  */
33 public class TimeZoneInfo {
34 
35     private final String mId;
36     private final TimeZone mTimeZone;
37     private final String mGenericName;
38     private final String mStandardName;
39     private final String mDaylightName;
40     private final String mExemplarLocation;
41     private final CharSequence mGmtOffset;
42 
TimeZoneInfo(Builder builder)43     public TimeZoneInfo(Builder builder) {
44         mTimeZone = builder.mTimeZone;
45         mId = mTimeZone.getID();
46         mGenericName = builder.mGenericName;
47         mStandardName = builder.mStandardName;
48         mDaylightName = builder.mDaylightName;
49         mExemplarLocation = builder.mExemplarLocation;
50         mGmtOffset = builder.mGmtOffset;
51     }
52 
getId()53     public String getId() {
54         return mId;
55     }
56 
getTimeZone()57     public TimeZone getTimeZone() {
58         return mTimeZone;
59     }
60 
getExemplarLocation()61     public String getExemplarLocation() {
62         return mExemplarLocation;
63     }
64 
getGenericName()65     public String getGenericName() {
66         return mGenericName;
67     }
68 
getStandardName()69     public String getStandardName() {
70         return mStandardName;
71     }
72 
getDaylightName()73     public String getDaylightName() {
74         return mDaylightName;
75     }
76 
getGmtOffset()77     public CharSequence getGmtOffset() {
78         return mGmtOffset;
79     }
80 
81     public static class Builder {
82         private final TimeZone mTimeZone;
83         private String mGenericName;
84         private String mStandardName;
85         private String mDaylightName;
86         private String mExemplarLocation;
87         private CharSequence mGmtOffset;
88 
Builder(TimeZone timeZone)89         public Builder(TimeZone timeZone) {
90             if (timeZone == null) {
91                 throw new IllegalArgumentException("TimeZone must not be null!");
92             }
93             mTimeZone = timeZone;
94         }
95 
setGenericName(String genericName)96         public Builder setGenericName(String genericName) {
97             this.mGenericName = genericName;
98             return this;
99         }
100 
setStandardName(String standardName)101         public Builder setStandardName(String standardName) {
102             this.mStandardName = standardName;
103             return this;
104         }
105 
setDaylightName(String daylightName)106         public Builder setDaylightName(String daylightName) {
107             mDaylightName = daylightName;
108             return this;
109         }
110 
setExemplarLocation(String exemplarLocation)111         public Builder setExemplarLocation(String exemplarLocation) {
112             mExemplarLocation = exemplarLocation;
113             return this;
114         }
115 
setGmtOffset(CharSequence gmtOffset)116         public Builder setGmtOffset(CharSequence gmtOffset) {
117             mGmtOffset = gmtOffset;
118             return this;
119         }
120 
build()121         public TimeZoneInfo build() {
122             if (TextUtils.isEmpty(mGmtOffset)) {
123                 throw new IllegalStateException("gmtOffset must not be empty!");
124             }
125             return new TimeZoneInfo(this);
126         }
127     }
128 
129     public static class Formatter {
130         private final Locale mLocale;
131         private final Date mNow;
132         private final TimeZoneFormat mTimeZoneFormat;
133 
Formatter(Locale locale, Date now)134         public Formatter(Locale locale, Date now) {
135             mLocale = locale;
136             mNow = now;
137             mTimeZoneFormat = TimeZoneFormat.getInstance(locale);
138         }
139 
140         /**
141          * @param timeZoneId Olson time zone id
142          * @return TimeZoneInfo containing time zone names, exemplar locations and GMT offset
143          */
format(String timeZoneId)144         public TimeZoneInfo format(String timeZoneId) {
145             TimeZone timeZone = TimeZone.getFrozenTimeZone(timeZoneId);
146             return format(timeZone);
147         }
148 
149         /**
150          * @param timeZone Olson time zone object
151          * @return TimeZoneInfo containing time zone names, exemplar locations and GMT offset
152          */
format(TimeZone timeZone)153         public TimeZoneInfo format(TimeZone timeZone) {
154             String canonicalZoneId = getCanonicalZoneId(timeZone);
155             final TimeZoneNames timeZoneNames = mTimeZoneFormat.getTimeZoneNames();
156             final java.util.TimeZone javaTimeZone = toJavaTimeZone(canonicalZoneId);
157             final CharSequence gmtOffset =
158                     ZoneGetter.getGmtOffsetText(mTimeZoneFormat, mLocale, javaTimeZone, mNow);
159             return new TimeZoneInfo.Builder(timeZone)
160                     .setGenericName(getTzNameForListDisplay(mLocale, timeZoneNames,
161                             canonicalZoneId, mNow, TimeZoneNames.NameType.LONG_GENERIC))
162                     .setStandardName(getTzNameForListDisplay(mLocale, timeZoneNames,
163                             canonicalZoneId, mNow, TimeZoneNames.NameType.LONG_STANDARD))
164                     .setDaylightName(getTzNameForListDisplay(mLocale, timeZoneNames,
165                             canonicalZoneId, mNow, TimeZoneNames.NameType.LONG_DAYLIGHT))
166                     .setExemplarLocation(capitalizeForStandaloneDisplay(mLocale,
167                             timeZoneNames.getExemplarLocationName(canonicalZoneId)))
168                     .setGmtOffset(gmtOffset)
169                     .build();
170         }
171 
getTzNameForListDisplay( Locale locale, TimeZoneNames timeZoneNames, String canonicalZoneId, Date now, TimeZoneNames.NameType nameType)172         private static String getTzNameForListDisplay(
173                 Locale locale, TimeZoneNames timeZoneNames, String canonicalZoneId, Date now,
174                 TimeZoneNames.NameType nameType) {
175             long nowEpochMillis = now.getTime();
176             String displayName = timeZoneNames.getDisplayName(
177                     canonicalZoneId, nameType, nowEpochMillis);
178             return capitalizeForStandaloneDisplay(locale, displayName);
179         }
180     }
181 
getJavaTimeZone()182     /* package-private */ java.util.TimeZone getJavaTimeZone() {
183         String canonicalZoneId = getCanonicalZoneId(mTimeZone);
184         return toJavaTimeZone(canonicalZoneId);
185     }
186 
toJavaTimeZone(String canonicalZoneId)187     private static java.util.TimeZone toJavaTimeZone(String canonicalZoneId) {
188         return java.util.TimeZone.getTimeZone(canonicalZoneId);
189     }
190 
getCanonicalZoneId(TimeZone timeZone)191     private static String getCanonicalZoneId(TimeZone timeZone) {
192         final String id = timeZone.getID();
193         final String canonicalId = TimeZone.getCanonicalID(id);
194         if (canonicalId != null) {
195             return canonicalId;
196         }
197         return id;
198     }
199 
200 }
201