blob: 12ead4e0a575a4c3b14caf5486dc2592f1543618 [file] [log] [blame]
Tony Mantlerb3543e02015-05-28 14:48:00 -07001/*
2 * Copyright (C) 2015 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.settingslib.datetime;
18
19import android.content.Context;
20import android.content.res.XmlResourceParser;
21import android.text.BidiFormatter;
22import android.text.TextDirectionHeuristics;
23import android.text.TextUtils;
24import android.util.Log;
25import android.view.View;
26
27import com.android.settingslib.R;
28
29import libcore.icu.TimeZoneNames;
30
31import org.xmlpull.v1.XmlPullParserException;
32
33import java.text.SimpleDateFormat;
34import java.util.ArrayList;
35import java.util.Calendar;
36import java.util.Date;
37import java.util.HashMap;
38import java.util.HashSet;
39import java.util.List;
40import java.util.Locale;
41import java.util.TimeZone;
42
43public class ZoneGetter {
44 private static final String TAG = "ZoneGetter";
45
46 private static final String XMLTAG_TIMEZONE = "timezone";
47
48 public static final String KEY_ID = "id"; // value: String
49 public static final String KEY_DISPLAYNAME = "name"; // value: String
50 public static final String KEY_GMT = "gmt"; // value: String
51 public static final String KEY_OFFSET = "offset"; // value: int (Integer)
52
53 private final List<HashMap<String, Object>> mZones = new ArrayList<>();
54 private final HashSet<String> mLocalZones = new HashSet<>();
55 private final Date mNow = Calendar.getInstance().getTime();
56 private final SimpleDateFormat mZoneNameFormatter = new SimpleDateFormat("zzzz");
57
58 public List<HashMap<String, Object>> getZones(Context context) {
59 for (String olsonId : TimeZoneNames.forLocale(Locale.getDefault())) {
60 mLocalZones.add(olsonId);
61 }
62 try {
63 XmlResourceParser xrp = context.getResources().getXml(R.xml.timezones);
64 while (xrp.next() != XmlResourceParser.START_TAG) {
65 continue;
66 }
67 xrp.next();
68 while (xrp.getEventType() != XmlResourceParser.END_TAG) {
69 while (xrp.getEventType() != XmlResourceParser.START_TAG) {
70 if (xrp.getEventType() == XmlResourceParser.END_DOCUMENT) {
71 return mZones;
72 }
73 xrp.next();
74 }
75 if (xrp.getName().equals(XMLTAG_TIMEZONE)) {
76 String olsonId = xrp.getAttributeValue(0);
77 addTimeZone(olsonId);
78 }
79 while (xrp.getEventType() != XmlResourceParser.END_TAG) {
80 xrp.next();
81 }
82 xrp.next();
83 }
84 xrp.close();
85 } catch (XmlPullParserException xppe) {
86 Log.e(TAG, "Ill-formatted timezones.xml file");
87 } catch (java.io.IOException ioe) {
88 Log.e(TAG, "Unable to read timezones.xml file");
89 }
90 return mZones;
91 }
92
93 private void addTimeZone(String olsonId) {
94 // We always need the "GMT-07:00" string.
95 final TimeZone tz = TimeZone.getTimeZone(olsonId);
96
97 // For the display name, we treat time zones within the country differently
98 // from other countries' time zones. So in en_US you'd get "Pacific Daylight Time"
99 // but in de_DE you'd get "Los Angeles" for the same time zone.
100 String displayName;
101 if (mLocalZones.contains(olsonId)) {
102 // Within a country, we just use the local name for the time zone.
103 mZoneNameFormatter.setTimeZone(tz);
104 displayName = mZoneNameFormatter.format(mNow);
105 } else {
106 // For other countries' time zones, we use the exemplar location.
107 final String localeName = Locale.getDefault().toString();
108 displayName = TimeZoneNames.getExemplarLocation(localeName, olsonId);
109 }
110
111 final HashMap<String, Object> map = new HashMap<>();
112 map.put(KEY_ID, olsonId);
113 map.put(KEY_DISPLAYNAME, displayName);
114 map.put(KEY_GMT, getTimeZoneText(tz, false));
115 map.put(KEY_OFFSET, tz.getOffset(mNow.getTime()));
116
117 mZones.add(map);
118 }
119
120 public static String getTimeZoneText(TimeZone tz, boolean includeName) {
121 Date now = new Date();
122
123 // Use SimpleDateFormat to format the GMT+00:00 string.
124 SimpleDateFormat gmtFormatter = new SimpleDateFormat("ZZZZ");
125 gmtFormatter.setTimeZone(tz);
126 String gmtString = gmtFormatter.format(now);
127
128 // Ensure that the "GMT+" stays with the "00:00" even if the digits are RTL.
129 BidiFormatter bidiFormatter = BidiFormatter.getInstance();
130 Locale l = Locale.getDefault();
131 boolean isRtl = TextUtils.getLayoutDirectionFromLocale(l) == View.LAYOUT_DIRECTION_RTL;
132 gmtString = bidiFormatter.unicodeWrap(gmtString,
133 isRtl ? TextDirectionHeuristics.RTL : TextDirectionHeuristics.LTR);
134
135 if (!includeName) {
136 return gmtString;
137 }
138
139 // Optionally append the time zone name.
140 SimpleDateFormat zoneNameFormatter = new SimpleDateFormat("zzzz");
141 zoneNameFormatter.setTimeZone(tz);
142 String zoneNameString = zoneNameFormatter.format(now);
143
144 // We don't use punctuation here to avoid having to worry about localizing that too!
145 return gmtString + " " + zoneNameString;
146 }
147}