| /* |
| * Copyright (C) 2019 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 android.timezone; |
| |
| import android.annotation.NonNull; |
| import android.annotation.Nullable; |
| import android.icu.util.TimeZone; |
| |
| import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.List; |
| import java.util.Objects; |
| |
| /** |
| * Information about a country's time zones. |
| * |
| * @hide |
| */ |
| public final class CountryTimeZones { |
| |
| /** |
| * A mapping to a time zone ID with some associated metadata. |
| * |
| * @hide |
| */ |
| public static final class TimeZoneMapping { |
| |
| @NonNull |
| private libcore.timezone.CountryTimeZones.TimeZoneMapping mDelegate; |
| |
| TimeZoneMapping(libcore.timezone.CountryTimeZones.TimeZoneMapping delegate) { |
| this.mDelegate = Objects.requireNonNull(delegate); |
| } |
| |
| /** |
| * Returns the ID for this mapping. The ID is a tzdb time zone identifier like |
| * "America/Los_Angeles" that can be used with methods such as {@link |
| * TimeZone#getFrozenTimeZone(String)}. See {@link #getTimeZone()} which returns a frozen |
| * {@link TimeZone} object. |
| */ |
| @NonNull |
| public String getTimeZoneId() { |
| return mDelegate.getTimeZoneId(); |
| } |
| |
| /** |
| * Returns a frozen {@link TimeZone} object for this mapping. |
| */ |
| @NonNull |
| public TimeZone getTimeZone() { |
| return mDelegate.getTimeZone(); |
| } |
| |
| @Override |
| public boolean equals(Object o) { |
| if (this == o) { |
| return true; |
| } |
| if (o == null || getClass() != o.getClass()) { |
| return false; |
| } |
| TimeZoneMapping that = (TimeZoneMapping) o; |
| return this.mDelegate.equals(that.mDelegate); |
| } |
| |
| @Override |
| public int hashCode() { |
| return this.mDelegate.hashCode(); |
| } |
| |
| @Override |
| public String toString() { |
| return mDelegate.toString(); |
| } |
| } |
| |
| /** |
| * The result of lookup up a time zone using offset information (and possibly more). |
| * |
| * @hide |
| */ |
| public static final class OffsetResult { |
| |
| private final TimeZone mTimeZone; |
| private final boolean mIsOnlyMatch; |
| |
| /** Creates an instance with the supplied information. */ |
| public OffsetResult(@NonNull TimeZone timeZone, boolean isOnlyMatch) { |
| mTimeZone = Objects.requireNonNull(timeZone); |
| mIsOnlyMatch = isOnlyMatch; |
| } |
| |
| /** |
| * Returns a time zone that matches the supplied criteria. |
| */ |
| @NonNull |
| public TimeZone getTimeZone() { |
| return mTimeZone; |
| } |
| |
| /** |
| * Returns {@code true} if there is only one matching time zone for the supplied criteria. |
| */ |
| public boolean isOnlyMatch() { |
| return mIsOnlyMatch; |
| } |
| |
| @Override |
| public boolean equals(Object o) { |
| if (this == o) { |
| return true; |
| } |
| if (o == null || getClass() != o.getClass()) { |
| return false; |
| } |
| OffsetResult that = (OffsetResult) o; |
| return mIsOnlyMatch == that.mIsOnlyMatch |
| && mTimeZone.getID().equals(that.mTimeZone.getID()); |
| } |
| |
| @Override |
| public int hashCode() { |
| return Objects.hash(mTimeZone, mIsOnlyMatch); |
| } |
| |
| @Override |
| public String toString() { |
| return "OffsetResult{" |
| + "mTimeZone=" + mTimeZone |
| + ", mIsOnlyMatch=" + mIsOnlyMatch |
| + '}'; |
| } |
| } |
| |
| @NonNull |
| private final libcore.timezone.CountryTimeZones mDelegate; |
| |
| CountryTimeZones(libcore.timezone.CountryTimeZones delegate) { |
| mDelegate = delegate; |
| } |
| |
| /** |
| * Returns true if the ISO code for the country is a case-insensitive match for the one |
| * supplied. |
| */ |
| public boolean matchesCountryCode(@NonNull String countryIso) { |
| return mDelegate.isForCountryCode(countryIso); |
| } |
| |
| /** |
| * Returns the default time zone ID for the country. Can return {@code null} in cases when no |
| * data is available or the time zone ID was not recognized. |
| */ |
| @Nullable |
| public String getDefaultTimeZoneId() { |
| return mDelegate.getDefaultTimeZoneId(); |
| } |
| |
| /** |
| * Returns the default time zone for the country. Can return {@code null} in cases when no data |
| * is available or the time zone ID was not recognized. |
| */ |
| @Nullable |
| public TimeZone getDefaultTimeZone() { |
| return mDelegate.getDefaultTimeZone(); |
| } |
| |
| /** |
| * Qualifier for a country's default time zone. {@code true} indicates that the country's |
| * default time zone would be a good choice <em>generally</em> when there's no UTC offset |
| * information available. This will only be {@code true} in countries with multiple zones where |
| * a large majority of the population is covered by only one of them. |
| */ |
| public boolean isDefaultTimeZoneBoosted() { |
| return mDelegate.isDefaultTimeZoneBoosted(); |
| } |
| |
| /** |
| * Returns {@code true} if the country has at least one time zone that uses UTC at the given |
| * time. This is an efficient check when trying to validate received UTC offset information. |
| * For example, there are situations when a detected zero UTC offset cannot be distinguished |
| * from "no information available" or a corrupted signal. This method is useful because checking |
| * offset information for large countries is relatively expensive but it is generally only the |
| * countries close to the prime meridian that use UTC at <em>any</em> time of the year. |
| * |
| * @param whenMillis the time the offset information is for in milliseconds since the beginning |
| * of the Unix epoch |
| */ |
| public boolean hasUtcZone(long whenMillis) { |
| return mDelegate.hasUtcZone(whenMillis); |
| } |
| |
| /** |
| * Returns a time zone for the country, if there is one, that matches the supplied properties. |
| * If there are multiple matches and the {@code bias} is one of them then it is returned, |
| * otherwise an arbitrary match is returned based on the {@link |
| * #getEffectiveTimeZoneMappingsAt(long)} ordering. |
| * |
| * @param whenMillis the UTC time to match against |
| * @param bias the time zone to prefer, can be {@code null} to indicate there is no preference |
| * @param totalOffsetMillis the offset from UTC at {@code whenMillis} |
| * @param isDst the Daylight Savings Time state at {@code whenMillis}. {@code true} means DST, |
| * {@code false} means not DST |
| * @return an {@link OffsetResult} with information about a matching zone, or {@code null} if |
| * there is no match |
| */ |
| @Nullable |
| public OffsetResult lookupByOffsetWithBias(long whenMillis, @Nullable TimeZone bias, |
| int totalOffsetMillis, boolean isDst) { |
| libcore.timezone.CountryTimeZones.OffsetResult delegateOffsetResult = |
| mDelegate.lookupByOffsetWithBias( |
| whenMillis, bias, totalOffsetMillis, isDst); |
| return delegateOffsetResult == null ? null : |
| new OffsetResult( |
| delegateOffsetResult.getTimeZone(), delegateOffsetResult.isOnlyMatch()); |
| } |
| |
| /** |
| * Returns a time zone for the country, if there is one, that matches the supplied properties. |
| * If there are multiple matches and the {@code bias} is one of them then it is returned, |
| * otherwise an arbitrary match is returned based on the {@link |
| * #getEffectiveTimeZoneMappingsAt(long)} ordering. |
| * |
| * @param whenMillis the UTC time to match against |
| * @param bias the time zone to prefer, can be {@code null} to indicate there is no preference |
| * @param totalOffsetMillis the offset from UTC at {@code whenMillis} |
| * @return an {@link OffsetResult} with information about a matching zone, or {@code null} if |
| * there is no match |
| */ |
| @Nullable |
| public OffsetResult lookupByOffsetWithBias(long whenMillis, @Nullable TimeZone bias, |
| int totalOffsetMillis) { |
| libcore.timezone.CountryTimeZones.OffsetResult delegateOffsetResult = |
| mDelegate.lookupByOffsetWithBias(whenMillis, bias, totalOffsetMillis); |
| return delegateOffsetResult == null ? null : |
| new OffsetResult( |
| delegateOffsetResult.getTimeZone(), delegateOffsetResult.isOnlyMatch()); |
| } |
| |
| /** |
| * Returns an immutable, ordered list of time zone mappings for the country in an undefined but |
| * "priority" order, filtered so that only "effective" time zone IDs are returned. An |
| * "effective" time zone is one that differs from another time zone used in the country after |
| * {@code whenMillis}. The list can be empty if there were no zones configured or the configured |
| * zone IDs were not recognized. |
| */ |
| @NonNull |
| public List<TimeZoneMapping> getEffectiveTimeZoneMappingsAt(long whenMillis) { |
| List<libcore.timezone.CountryTimeZones.TimeZoneMapping> delegateList = |
| mDelegate.getEffectiveTimeZoneMappingsAt(whenMillis); |
| |
| List<TimeZoneMapping> toReturn = new ArrayList<>(delegateList.size()); |
| for (libcore.timezone.CountryTimeZones.TimeZoneMapping delegateMapping : delegateList) { |
| toReturn.add(new TimeZoneMapping(delegateMapping)); |
| } |
| return Collections.unmodifiableList(toReturn); |
| } |
| |
| @Override |
| public boolean equals(Object o) { |
| if (this == o) { |
| return true; |
| } |
| if (o == null || getClass() != o.getClass()) { |
| return false; |
| } |
| CountryTimeZones that = (CountryTimeZones) o; |
| return mDelegate.equals(that.mDelegate); |
| } |
| |
| @Override |
| public int hashCode() { |
| return Objects.hash(mDelegate); |
| } |
| |
| @Override |
| public String toString() { |
| return mDelegate.toString(); |
| } |
| } |