• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019 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.car.developeroptions.datetime.timezone;
18 
19 import android.content.Context;
20 import android.icu.text.DateFormat;
21 import android.icu.text.DisplayContext;
22 import android.icu.text.SimpleDateFormat;
23 import android.icu.util.BasicTimeZone;
24 import android.icu.util.Calendar;
25 import android.icu.util.TimeZone;
26 import android.icu.util.TimeZoneTransition;
27 
28 import androidx.annotation.VisibleForTesting;
29 
30 import com.android.car.developeroptions.R;
31 import com.android.car.developeroptions.core.BasePreferenceController;
32 
33 import java.util.Date;
34 
35 public class TimeZoneInfoPreferenceController extends BasePreferenceController {
36 
37     @VisibleForTesting
38     Date mDate;
39     private TimeZoneInfo mTimeZoneInfo;
40     private final DateFormat mDateFormat;
41 
TimeZoneInfoPreferenceController(Context context, String key)42     public TimeZoneInfoPreferenceController(Context context, String key) {
43         super(context, key);
44         mDateFormat = DateFormat.getDateInstance(SimpleDateFormat.LONG);
45         mDateFormat.setContext(DisplayContext.CAPITALIZATION_NONE);
46         mDate = new Date();
47     }
48 
49     @Override
getAvailabilityStatus()50     public int getAvailabilityStatus() {
51         return mTimeZoneInfo != null ? AVAILABLE_UNSEARCHABLE : UNSUPPORTED_ON_DEVICE;
52     }
53 
54     @Override
getSummary()55     public CharSequence getSummary() {
56         return mTimeZoneInfo == null ? "" : formatInfo(mTimeZoneInfo);
57     }
58 
setTimeZoneInfo(TimeZoneInfo timeZoneInfo)59     public void setTimeZoneInfo(TimeZoneInfo timeZoneInfo) {
60         mTimeZoneInfo = timeZoneInfo;
61     }
62 
formatOffsetAndName(TimeZoneInfo item)63     private CharSequence formatOffsetAndName(TimeZoneInfo item) {
64         String name = item.getGenericName();
65         if (name == null) {
66             if (item.getTimeZone().inDaylightTime(mDate)) {
67                 name = item.getDaylightName();
68             } else {
69                 name = item.getStandardName();
70             }
71         }
72         if (name == null) {
73             return item.getGmtOffset().toString();
74         } else {
75             return SpannableUtil.getResourcesText(mContext.getResources(),
76                     R.string.zone_info_offset_and_name, item.getGmtOffset(),
77                     name);
78         }
79     }
80 
formatInfo(TimeZoneInfo item)81     private CharSequence formatInfo(TimeZoneInfo item) {
82         final CharSequence offsetAndName = formatOffsetAndName(item);
83         final TimeZone timeZone = item.getTimeZone();
84         if (!timeZone.observesDaylightTime()) {
85             return mContext.getString(R.string.zone_info_footer_no_dst, offsetAndName);
86         }
87 
88         final TimeZoneTransition nextDstTransition = findNextDstTransition(timeZone);
89         if (nextDstTransition == null) {
90             return null;
91         }
92         final boolean toDst = nextDstTransition.getTo().getDSTSavings() != 0;
93         String timeType = toDst ? item.getDaylightName() : item.getStandardName();
94         if (timeType == null) {
95             // Fall back to generic "summer time" and "standard time" if the time zone has no
96             // specific names.
97             timeType = toDst ?
98                     mContext.getString(R.string.zone_time_type_dst) :
99                     mContext.getString(R.string.zone_time_type_standard);
100 
101         }
102         final Calendar transitionTime = Calendar.getInstance(timeZone);
103         transitionTime.setTimeInMillis(nextDstTransition.getTime());
104         final String date = mDateFormat.format(transitionTime);
105         return SpannableUtil.getResourcesText(mContext.getResources(),
106                 R.string.zone_info_footer, offsetAndName, timeType, date);
107     }
108 
findNextDstTransition(TimeZone timeZone)109     private TimeZoneTransition findNextDstTransition(TimeZone timeZone) {
110         if (!(timeZone instanceof BasicTimeZone)) {
111             return null;
112         }
113         final BasicTimeZone basicTimeZone = (BasicTimeZone) timeZone;
114         TimeZoneTransition transition = basicTimeZone.getNextTransition(
115                 mDate.getTime(), /* inclusive */ false);
116         do {
117             if (transition.getTo().getDSTSavings() != transition.getFrom().getDSTSavings()) {
118                 break;
119             }
120             transition = basicTimeZone.getNextTransition(
121                     transition.getTime(), /*inclusive */ false);
122         } while (transition != null);
123         return transition;
124     }
125 }
126