Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 273986db authored by Neil Fuller's avatar Neil Fuller Committed by Gerrit Code Review
Browse files

Merge "Remove some usages of NitzData.isDst()"

parents 4e5522ba c03c9774
Loading
Loading
Loading
Loading
+25 −3
Original line number Diff line number Diff line
@@ -26,7 +26,7 @@ import java.util.Calendar;
import java.util.TimeZone;

/**
 * Represents NITZ data. Various static methods are provided to help with parsing and intepretation
 * Represents NITZ data. Various static methods are provided to help with parsing and interpretation
 * of NITZ data.
 *
 * {@hide}
@@ -153,7 +153,11 @@ public final class NitzData {

    /**
     * Returns the total offset to apply to the {@link #getCurrentTimeInMillis()} to arrive at a
     * local time.
     * local time. NITZ is limited in only being able to express total offsets in multiples of 15
     * minutes.
     *
     * <p>Note that some time zones change offset during the year for reasons other than "daylight
     * savings", e.g. for Ramadan. This is not well handled by most date / time APIs.
     */
    public int getLocalOffsetMillis() {
        return mZoneOffset;
@@ -162,7 +166,25 @@ public final class NitzData {
    /**
     * Returns the offset (already included in {@link #getLocalOffsetMillis()}) associated with
     * Daylight Savings Time (DST). This field is optional: {@code null} means the DST offset is
     * unknown.
     * unknown. NITZ is limited in only being able to express DST offsets in positive multiples of
     * one or two hours.
     *
     * <p>Callers should remember that standard time / DST is a matter of convention: it has
     * historically been assumed by NITZ and many date/time APIs that DST happens in the summer and
     * the "raw" offset will increase during this time, usually by one hour. However, the tzdb
     * maintainers have moved to different conventions on a country-by-country basis so that some
     * summer times are considered the "standard" time (i.e. in this model winter time is the "DST"
     * and a negative adjustment, usually of (negative) one hour.
     *
     * <p>There is nothing that says NITZ and tzdb need to treat DST conventions the same.
     *
     * <p>At the time of writing Android date/time APIs are sticking with the historic tzdb
     * convention that DST is used in summer time and is <em>always</em> a positive offset but this
     * could change in future. If Android or carriers change the conventions used then it might make
     * NITZ comparisons with tzdb information more error-prone.
     *
     * <p>See also {@link #getLocalOffsetMillis()} for other reasons besides DST that a local offset
     * may change.
     */
    public Integer getDstAdjustmentMillis() {
        return mDstOffset;
+1 −1
Original line number Diff line number Diff line
@@ -263,7 +263,7 @@ public final class NitzStateMachineImpl implements NitzStateMachine {
        }

        NitzData newNitzData = nitzSignal.getValue();
        boolean zeroOffsetNitz = newNitzData.getLocalOffsetMillis() == 0 && !newNitzData.isDst();
        boolean zeroOffsetNitz = newNitzData.getLocalOffsetMillis() == 0;
        return zeroOffsetNitz && !countryUsesUtc(isoCountryCode, nitzSignal);
    }

+36 −13
Original line number Diff line number Diff line
@@ -23,7 +23,6 @@ import libcore.timezone.CountryTimeZones;
import libcore.timezone.CountryTimeZones.TimeZoneMapping;
import libcore.timezone.TimeZoneFinder;

import java.util.Date;
import java.util.List;
import java.util.Objects;

@@ -314,30 +313,36 @@ public class TimeZoneLookupHelper {

    private static OffsetResult lookupByNitzStatic(NitzData nitzData) {
        int utcOffsetMillis = nitzData.getLocalOffsetMillis();
        boolean isDst = nitzData.isDst();
        long timeMillis = nitzData.getCurrentTimeInMillis();

        // Android NITZ time zone matching doesn't try to do a precise match using the DST offset
        // supplied by the carrier. It only considers whether or not the carrier suggests local time
        // is DST (if known). NITZ is limited in only being able to express DST offsets in whole
        // hours and the DST info is optional.
        Integer dstAdjustmentMillis = nitzData.getDstAdjustmentMillis();
        Boolean isDst = dstAdjustmentMillis == null ? null : dstAdjustmentMillis != 0;

        OffsetResult match = lookupByInstantOffsetDst(timeMillis, utcOffsetMillis, isDst);
        if (match == null) {
            // Couldn't find a proper timezone.  Perhaps the DST data is wrong.
            match = lookupByInstantOffsetDst(timeMillis, utcOffsetMillis, !isDst);
        if (match == null && isDst != null) {
            // This branch is extremely unlikely and could probably be removed. The match above will
            // have searched the entire tzdb for a zone with the same total offset and isDst state.
            // Here we try another match but use "null" for isDst to indicate that only the total
            // offset should be considered. If, by the end of this, there isn't a match then the
            // current offset suggested by the carrier must be highly unusual.
            match = lookupByInstantOffsetDst(timeMillis, utcOffsetMillis, null /* isDst */);
        }
        return match;
    }

    private static OffsetResult lookupByInstantOffsetDst(long timeMillis, int utcOffsetMillis,
            boolean isDst) {
        int rawOffset = utcOffsetMillis;
        if (isDst) {
            rawOffset -= MS_PER_HOUR;
        }
        String[] zones = TimeZone.getAvailableIDs(rawOffset);
            Boolean isDst) {

        String[] zones = TimeZone.getAvailableIDs();
        TimeZone match = null;
        Date d = new Date(timeMillis);
        boolean isOnlyMatch = true;
        for (String zone : zones) {
            TimeZone tz = TimeZone.getFrozenTimeZone(zone);
            if (tz.getOffset(timeMillis) == utcOffsetMillis && tz.inDaylightTime(d) == isDst) {
            if (offsetMatchesAtTime(tz, utcOffsetMillis, isDst, timeMillis)) {
                if (match == null) {
                    match = tz;
                } else {
@@ -353,6 +358,24 @@ public class TimeZoneLookupHelper {
        return new OffsetResult(match, isOnlyMatch);
    }

    /**
     * Returns {@code true} if the specified {@code totalOffset} and {@code isDst} would be valid in
     * the {@code timeZone} at time {@code whenMillis}. {@code totalOffetMillis} is always matched.
     * If {@code isDst} is {@code null} this means the DST state is unknown so DST state is ignored.
     * If {@code isDst} is not {@code null} then it is also matched.
     */
    private static boolean offsetMatchesAtTime(TimeZone timeZone, int totalOffsetMillis,
            Boolean isDst, long whenMillis) {
        int[] offsets = new int[2];
        timeZone.getOffset(whenMillis, false /* local */, offsets);

        if (totalOffsetMillis != (offsets[0] + offsets[1])) {
            return false;
        }

        return isDst == null || isDst == (offsets[1] != 0);
    }

    /**
     * Returns {@code true} if the supplied (lower-case) ISO country code is for a country known to
     * use a raw offset of zero from UTC at the time specified.