Capitalize Settings UI time zone display name strings for languanges like Polish for standalone locations like summaries and lists. The motivating example case is the string for "Coordinated Universal Time" in Polish, which is not capitalized in CLDR, as they capitalize for the middle of sentences by default. In English, Coordinated Universal Time is already capitalized, but the Polish string is not. With this commit all "display name"-like strings have been capitalized (region names, exemplar locations, time zone names like "Coordinated Universal Time" and "British Summer Time") for completeness. For the Polish case, many are already capitalized, but capitalizing the first letter is therefore a no-op. The "GMT+xx:xx"-style strings have not been changed. Bug: 190109975 Test: Visual inspection in English and Polish of UTC, United States, Russia in the time zone picker and the date & time screen on mobile Change-Id: I57d915ac1e30e22cc05e605fcb7d46b102fa8ce1
201 lines
6.8 KiB
Java
201 lines
6.8 KiB
Java
/*
|
|
* Copyright (C) 2017 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
package com.android.settings.datetime.timezone;
|
|
|
|
import static com.android.settingslib.datetime.ZoneGetter.capitalizeForStandaloneDisplay;
|
|
|
|
import android.icu.text.TimeZoneFormat;
|
|
import android.icu.text.TimeZoneNames;
|
|
import android.icu.util.TimeZone;
|
|
import android.text.TextUtils;
|
|
|
|
import com.android.settingslib.datetime.ZoneGetter;
|
|
|
|
import java.util.Date;
|
|
import java.util.Locale;
|
|
|
|
/**
|
|
* Data object containing information for displaying a time zone for the user to select.
|
|
*/
|
|
public class TimeZoneInfo {
|
|
|
|
private final String mId;
|
|
private final TimeZone mTimeZone;
|
|
private final String mGenericName;
|
|
private final String mStandardName;
|
|
private final String mDaylightName;
|
|
private final String mExemplarLocation;
|
|
private final CharSequence mGmtOffset;
|
|
|
|
public TimeZoneInfo(Builder builder) {
|
|
mTimeZone = builder.mTimeZone;
|
|
mId = mTimeZone.getID();
|
|
mGenericName = builder.mGenericName;
|
|
mStandardName = builder.mStandardName;
|
|
mDaylightName = builder.mDaylightName;
|
|
mExemplarLocation = builder.mExemplarLocation;
|
|
mGmtOffset = builder.mGmtOffset;
|
|
}
|
|
|
|
public String getId() {
|
|
return mId;
|
|
}
|
|
|
|
public TimeZone getTimeZone() {
|
|
return mTimeZone;
|
|
}
|
|
|
|
public String getExemplarLocation() {
|
|
return mExemplarLocation;
|
|
}
|
|
|
|
public String getGenericName() {
|
|
return mGenericName;
|
|
}
|
|
|
|
public String getStandardName() {
|
|
return mStandardName;
|
|
}
|
|
|
|
public String getDaylightName() {
|
|
return mDaylightName;
|
|
}
|
|
|
|
public CharSequence getGmtOffset() {
|
|
return mGmtOffset;
|
|
}
|
|
|
|
public static class Builder {
|
|
private final TimeZone mTimeZone;
|
|
private String mGenericName;
|
|
private String mStandardName;
|
|
private String mDaylightName;
|
|
private String mExemplarLocation;
|
|
private CharSequence mGmtOffset;
|
|
|
|
public Builder(TimeZone timeZone) {
|
|
if (timeZone == null) {
|
|
throw new IllegalArgumentException("TimeZone must not be null!");
|
|
}
|
|
mTimeZone = timeZone;
|
|
}
|
|
|
|
public Builder setGenericName(String genericName) {
|
|
this.mGenericName = genericName;
|
|
return this;
|
|
}
|
|
|
|
public Builder setStandardName(String standardName) {
|
|
this.mStandardName = standardName;
|
|
return this;
|
|
}
|
|
|
|
public Builder setDaylightName(String daylightName) {
|
|
mDaylightName = daylightName;
|
|
return this;
|
|
}
|
|
|
|
public Builder setExemplarLocation(String exemplarLocation) {
|
|
mExemplarLocation = exemplarLocation;
|
|
return this;
|
|
}
|
|
|
|
public Builder setGmtOffset(CharSequence gmtOffset) {
|
|
mGmtOffset = gmtOffset;
|
|
return this;
|
|
}
|
|
|
|
public TimeZoneInfo build() {
|
|
if (TextUtils.isEmpty(mGmtOffset)) {
|
|
throw new IllegalStateException("gmtOffset must not be empty!");
|
|
}
|
|
return new TimeZoneInfo(this);
|
|
}
|
|
}
|
|
|
|
public static class Formatter {
|
|
private final Locale mLocale;
|
|
private final Date mNow;
|
|
private final TimeZoneFormat mTimeZoneFormat;
|
|
|
|
public Formatter(Locale locale, Date now) {
|
|
mLocale = locale;
|
|
mNow = now;
|
|
mTimeZoneFormat = TimeZoneFormat.getInstance(locale);
|
|
}
|
|
|
|
/**
|
|
* @param timeZoneId Olson time zone id
|
|
* @return TimeZoneInfo containing time zone names, exemplar locations and GMT offset
|
|
*/
|
|
public TimeZoneInfo format(String timeZoneId) {
|
|
TimeZone timeZone = TimeZone.getFrozenTimeZone(timeZoneId);
|
|
return format(timeZone);
|
|
}
|
|
|
|
/**
|
|
* @param timeZone Olson time zone object
|
|
* @return TimeZoneInfo containing time zone names, exemplar locations and GMT offset
|
|
*/
|
|
public TimeZoneInfo format(TimeZone timeZone) {
|
|
String canonicalZoneId = getCanonicalZoneId(timeZone);
|
|
final TimeZoneNames timeZoneNames = mTimeZoneFormat.getTimeZoneNames();
|
|
final java.util.TimeZone javaTimeZone = toJavaTimeZone(canonicalZoneId);
|
|
final CharSequence gmtOffset =
|
|
ZoneGetter.getGmtOffsetText(mTimeZoneFormat, mLocale, javaTimeZone, mNow);
|
|
return new TimeZoneInfo.Builder(timeZone)
|
|
.setGenericName(getTzNameForListDisplay(mLocale, timeZoneNames,
|
|
canonicalZoneId, mNow, TimeZoneNames.NameType.LONG_GENERIC))
|
|
.setStandardName(getTzNameForListDisplay(mLocale, timeZoneNames,
|
|
canonicalZoneId, mNow, TimeZoneNames.NameType.LONG_STANDARD))
|
|
.setDaylightName(getTzNameForListDisplay(mLocale, timeZoneNames,
|
|
canonicalZoneId, mNow, TimeZoneNames.NameType.LONG_DAYLIGHT))
|
|
.setExemplarLocation(capitalizeForStandaloneDisplay(mLocale,
|
|
timeZoneNames.getExemplarLocationName(canonicalZoneId)))
|
|
.setGmtOffset(gmtOffset)
|
|
.build();
|
|
}
|
|
|
|
private static String getTzNameForListDisplay(
|
|
Locale locale, TimeZoneNames timeZoneNames, String canonicalZoneId, Date now,
|
|
TimeZoneNames.NameType nameType) {
|
|
long nowEpochMillis = now.getTime();
|
|
String displayName = timeZoneNames.getDisplayName(
|
|
canonicalZoneId, nameType, nowEpochMillis);
|
|
return capitalizeForStandaloneDisplay(locale, displayName);
|
|
}
|
|
}
|
|
|
|
/* package-private */ java.util.TimeZone getJavaTimeZone() {
|
|
String canonicalZoneId = getCanonicalZoneId(mTimeZone);
|
|
return toJavaTimeZone(canonicalZoneId);
|
|
}
|
|
|
|
private static java.util.TimeZone toJavaTimeZone(String canonicalZoneId) {
|
|
return java.util.TimeZone.getTimeZone(canonicalZoneId);
|
|
}
|
|
|
|
private static String getCanonicalZoneId(TimeZone timeZone) {
|
|
final String id = timeZone.getID();
|
|
final String canonicalId = TimeZone.getCanonicalID(id);
|
|
if (canonicalId != null) {
|
|
return canonicalId;
|
|
}
|
|
return id;
|
|
}
|
|
|
|
}
|