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