ICU-21490 Exposing getOffsetFromLocal for ICU4J

See #1609
diff --git a/icu4j/main/classes/core/src/com/ibm/icu/impl/OlsonTimeZone.java b/icu4j/main/classes/core/src/com/ibm/icu/impl/OlsonTimeZone.java
index 0d315b1..d514966 100644
--- a/icu4j/main/classes/core/src/com/ibm/icu/impl/OlsonTimeZone.java
+++ b/icu4j/main/classes/core/src/com/ibm/icu/impl/OlsonTimeZone.java
@@ -280,11 +280,11 @@
      */
     @Override
     public void getOffsetFromLocal(long date,
-            int nonExistingTimeOpt, int duplicatedTimeOpt, int[] offsets) {
+            LocalOption nonExistingTimeOpt, LocalOption duplicatedTimeOpt, int[] offsets) {
         if (finalZone != null && date >= finalStartMillis) {
             finalZone.getOffsetFromLocal(date, nonExistingTimeOpt, duplicatedTimeOpt, offsets);
         } else {
-            getHistoricalOffset(date, true, nonExistingTimeOpt, duplicatedTimeOpt, offsets);
+            getHistoricalOffset(date, true, getLocalOptionValue(nonExistingTimeOpt), getLocalOptionValue(duplicatedTimeOpt), offsets);
         }
     }
 
@@ -1296,4 +1296,4 @@
         tz.isFrozen = false;
         return tz;
     }
-}
+}
\ No newline at end of file
diff --git a/icu4j/main/classes/core/src/com/ibm/icu/text/SimpleDateFormat.java b/icu4j/main/classes/core/src/com/ibm/icu/text/SimpleDateFormat.java
index 040258c..05131f5 100644
--- a/icu4j/main/classes/core/src/com/ibm/icu/text/SimpleDateFormat.java
+++ b/icu4j/main/classes/core/src/com/ibm/icu/text/SimpleDateFormat.java
@@ -37,6 +37,7 @@
 import com.ibm.icu.text.TimeZoneFormat.Style;
 import com.ibm.icu.text.TimeZoneFormat.TimeType;
 import com.ibm.icu.util.BasicTimeZone;
+import com.ibm.icu.util.BasicTimeZone.LocalOption;
 import com.ibm.icu.util.Calendar;
 import com.ibm.icu.util.HebrewCalendar;
 import com.ibm.icu.util.Output;
@@ -2710,10 +2711,10 @@
                     if (btz != null) {
                         if (tztype == TimeType.STANDARD) {
                             btz.getOffsetFromLocal(localMillis,
-                                    BasicTimeZone.LOCAL_STD, BasicTimeZone.LOCAL_STD, offsets);
+                                    LocalOption.STANDARD_FORMER, LocalOption.STANDARD_LATTER, offsets);
                         } else {
                             btz.getOffsetFromLocal(localMillis,
-                                    BasicTimeZone.LOCAL_DST, BasicTimeZone.LOCAL_DST, offsets);
+                                    LocalOption.DAYLIGHT_FORMER, LocalOption.DAYLIGHT_LATTER, offsets);
                         }
                     } else {
                         // No good way to resolve ambiguous time at transition,
diff --git a/icu4j/main/classes/core/src/com/ibm/icu/util/BasicTimeZone.java b/icu4j/main/classes/core/src/com/ibm/icu/util/BasicTimeZone.java
index abef756..5d56a39 100644
--- a/icu4j/main/classes/core/src/com/ibm/icu/util/BasicTimeZone.java
+++ b/icu4j/main/classes/core/src/com/ibm/icu/util/BasicTimeZone.java
@@ -36,7 +36,7 @@
     /**
      * {@icu} Returns the first time zone transition after the base time.
      * <p>Example code:{@.jcite com.ibm.icu.samples.util.timezone.BasicTimeZoneExample:---getNextTransitionExample}
-     * 
+     *
      * @param base      The base time.
      * @param inclusive Whether the base time is inclusive or not.
      *
@@ -105,7 +105,7 @@
      *
      * @stable ICU 3.8
      */
-    public boolean hasEquivalentTransitions(TimeZone tz, long start, long end, 
+    public boolean hasEquivalentTransitions(TimeZone tz, long start, long end,
                                             boolean ignoreDstAmount) {
         if (this == tz) {
             return true;
@@ -244,7 +244,7 @@
         }
 
         BitSet isProcessed = new BitSet(all.length);
-        List<TimeZoneRule> filteredRules = new LinkedList<TimeZoneRule>();
+        List<TimeZoneRule> filteredRules = new LinkedList<>();
 
         // Create initial rule
         TimeZoneRule initial = new InitialTimeZoneRule(tzt.getTo().getName(),
@@ -434,16 +434,16 @@
                         // Check if the next next transition is either DST->STD or STD->DST
                         // and within roughly 1 year from the next transition
                         if (((tr.getFrom().getDSTSavings() == 0 && tr.getTo().getDSTSavings() != 0)
-                                || (tr.getFrom().getDSTSavings() != 0 
+                                || (tr.getFrom().getDSTSavings() != 0
                                     && tr.getTo().getDSTSavings() == 0))
                             && nextTransitionTime + MILLIS_PER_YEAR > tr.getTime()) {
                             // Generate another DOW rule
                             dtfields = Grego.timeToFields(tr.getTime()
-                                    + tr.getFrom().getRawOffset() + tr.getFrom().getDSTSavings(), 
+                                    + tr.getFrom().getRawOffset() + tr.getFrom().getDSTSavings(),
                                                           dtfields);
-                            weekInMonth = Grego.getDayOfWeekInMonth(dtfields[0], dtfields[1], 
+                            weekInMonth = Grego.getDayOfWeekInMonth(dtfields[0], dtfields[1],
                                                                     dtfields[2]);
-                            dtr = new DateTimeRule(dtfields[1], weekInMonth, dtfields[3], 
+                            dtr = new DateTimeRule(dtfields[1], weekInMonth, dtfields[3],
                                                    dtfields[5], DateTimeRule.WALL_TIME);
                             secondRule = new AnnualTimeZoneRule(tr.getTo().getName(),
                                     tr.getTo().getRawOffset(), tr.getTo().getDSTSavings(),
@@ -472,22 +472,22 @@
                                     && tr.getTo().getDSTSavings() == 0)) {
                             // Generate another DOW rule
                             dtfields = Grego.timeToFields(tr.getTime()
-                                    + tr.getFrom().getRawOffset() + tr.getFrom().getDSTSavings(), 
+                                    + tr.getFrom().getRawOffset() + tr.getFrom().getDSTSavings(),
                                                           dtfields);
-                            weekInMonth = Grego.getDayOfWeekInMonth(dtfields[0], dtfields[1], 
+                            weekInMonth = Grego.getDayOfWeekInMonth(dtfields[0], dtfields[1],
                                                                     dtfields[2]);
-                            dtr = new DateTimeRule(dtfields[1], weekInMonth, dtfields[3], 
+                            dtr = new DateTimeRule(dtfields[1], weekInMonth, dtfields[3],
                                                    dtfields[5], DateTimeRule.WALL_TIME);
 
                             // second rule raw/dst offsets should match raw/dst offsets
                             // at the given time
                             secondRule = new AnnualTimeZoneRule(
-                                tr.getTo().getName(), initialRaw, initialDst, dtr, 
+                                tr.getTo().getName(), initialRaw, initialDst, dtr,
                                 annualRules[0].getStartYear() - 1, AnnualTimeZoneRule.MAX_YEAR);
 
                             // Check if this rule start after the first rule after the
                             // specified date
-                            Date d = secondRule.getNextStart(date, tr.getFrom().getRawOffset(), 
+                            Date d = secondRule.getNextStart(date, tr.getFrom().getRawOffset(),
                                                              tr.getFrom().getDSTSavings(), false);
                             if (d.getTime() > nextTransitionTime) {
                                 // We can use this rule as the second transition rule
@@ -536,44 +536,123 @@
     }
 
     /**
-     * {@icu} The time type option for standard time used by
-     * {@link #getOffsetFromLocal(long, int, int, int[])}
+     * {@icu} Options used by {@link #getOffsetFromLocal(long, LocalOption, LocalOption, int[])}
+     * to specify how to interpret an input time when it does not exist, or when it is ambiguous,
+     * around a time zone transition.
+     *
+     * @draft ICU 69
+     * @provisional This API might change or be removed in a future release.
+     */
+    public static enum LocalOption {
+        /**
+         * An input time is always interpreted as local time before
+         * a time zone transition.
+         * @draft ICU 69
+         * @provisional This API might change or be removed in a future release.
+         */
+        FORMER(0x04),
+        /**
+         * An input time is always interpreted as local time after
+         * a time zone transition.
+         * @draft ICU 69
+         * @provisional This API might change or be removed in a future release.
+         */
+        LATTER(0x0C),
+        /**
+         * An input time is interpreted as standard time when local
+         * time is switched to/from daylight saving time. When both
+         * sides of a time zone transition are standard time,
+         * or daylight saving time, the local time before the
+         * transition is used.
+         * @draft ICU 69
+         * @provisional This API might change or be removed in a future release.
+         */
+        STANDARD_FORMER(0x05),
+        /**
+         * An input time is interpreted as standard time when local
+         * time is switched to/from daylight saving time. When both
+         * sides of a time zone transition are standard time,
+         * or daylight saving time, the local time after the
+         * transition is used.
+         * @draft ICU 69
+         * @provisional This API might change or be removed in a future release.
+         */
+        STANDARD_LATTER(0x0D),
+        /**
+         * An input time is interpreted as daylight saving time when
+         * local time is switched to/from standard time. When both
+         * sides of a time zone transition are standard time,
+         * or daylight saving time, the local time before the
+         * transition is used.
+         * @draft ICU 69
+         * @provisional This API might change or be removed in a future release.
+         */
+        DAYLIGHT_FORMER(0x07),
+        /**
+         * An input time is interpreted as daylight saving time when
+         * local time is switched to/from standard time. When both
+         * sides of a time zone transition are standard time,
+         * or daylight saving time, the local time after the
+         * transition is used.
+         * @draft ICU 69
+         * @provisional This API might change or be removed in a future release.
+         */
+        DAYLIGHT_LATTER(0x0F);
+
+        private int flagVal;
+
+        LocalOption(int flagVal) {
+            this.flagVal = flagVal;
+        }
+    }
+
+    /**
+     * Get {@link LocalOption}'s internal flag value. This is used by ICU internal
+     * implementation only.
+     * @param locOpt    A LocalOption
+     * @return LocalOption's internal flag value.
      * @internal
      * @deprecated This API is ICU internal only.
      */
     @Deprecated
-    public static final int LOCAL_STD = 0x01;
+    protected static int getLocalOptionValue(LocalOption locOpt) {
+        return locOpt.flagVal;
+    }
 
     /**
-     * {@icu} The time type option for daylight saving time used by
-     * {@link #getOffsetFromLocal(long, int, int, int[])}
+     * The time type option for standard time used by internal implementation.
      * @internal
      * @deprecated This API is ICU internal only.
      */
     @Deprecated
-    public static final int LOCAL_DST = 0x03;
+    protected static final int LOCAL_STD = 0x01;
 
     /**
-     * {@icu} The option designate former time to be used by
-     * {@link #getOffsetFromLocal(long, int, int, int[])}
+     * The time type option for daylight saving time used internally.
      * @internal
      * @deprecated This API is ICU internal only.
      */
     @Deprecated
-    public static final int LOCAL_FORMER = 0x04;
+    protected static final int LOCAL_DST = 0x03;
 
     /**
-     * {@icu} The option designate latter time to be used by
-     * {@link #getOffsetFromLocal(long, int, int, int[])}
+     * The option designate former time used by internal implementation.
      * @internal
      * @deprecated This API is ICU internal only.
      */
     @Deprecated
-    public static final int LOCAL_LATTER = 0x0C;
+    protected static final int LOCAL_FORMER = 0x04;
 
     /**
-     * {@icu} The bit mask for the time type option used by
-     * {@link #getOffsetFromLocal(long, int, int, int[])}
+     * The option designate latter time used by internal implementation.
+     * @internal
+     * @deprecated This API is ICU internal only.
+     */
+    @Deprecated
+    protected static final int LOCAL_LATTER = 0x0C;
+
+    /**
+     * The bit mask for the time type option used by internal implementation.
      * @internal
      * @deprecated This API is ICU internal only.
      */
@@ -581,8 +660,7 @@
     protected static final int STD_DST_MASK = 0x03;
 
     /**
-     * {@icu} The bit mask for the former/latter option used by
-     * {@link #getOffsetFromLocal(long, int, int, int[])}
+     * The bit mask for the former/latter option used by internal implementation.
      * @internal
      * @deprecated This API is ICU internal only.
      */
@@ -591,12 +669,11 @@
 
     /**
      * {@icu} Returns time zone offsets from local wall time.
-     * @internal
-     * @deprecated This API is ICU internal only.
+     * @draft ICU 69
+     * @provisional This API might change or be removed in a future release.
      */
-    @Deprecated
     public void getOffsetFromLocal(long date,
-            int nonExistingTimeOpt, int duplicatedTimeOpt, int[] offsets) {
+            LocalOption nonExistingTimeOpt, LocalOption duplicatedTimeOpt, int[] offsets) {
         throw new IllegalStateException("Not implemented");
     }
 
diff --git a/icu4j/main/classes/core/src/com/ibm/icu/util/Calendar.java b/icu4j/main/classes/core/src/com/ibm/icu/util/Calendar.java
index 0aeb7e9..edfc8a7 100644
--- a/icu4j/main/classes/core/src/com/ibm/icu/util/Calendar.java
+++ b/icu4j/main/classes/core/src/com/ibm/icu/util/Calendar.java
@@ -29,6 +29,7 @@
 import com.ibm.icu.text.DateFormatSymbols;
 import com.ibm.icu.text.DateTimePatternGenerator;
 import com.ibm.icu.text.SimpleDateFormat;
+import com.ibm.icu.util.BasicTimeZone.LocalOption;
 import com.ibm.icu.util.ULocale.Category;
 
 /**
@@ -5725,8 +5726,8 @@
         int[] offsets = new int[2];
         long wall = millis + millisInDay;
         if (zone instanceof BasicTimeZone) {
-            int duplicatedTimeOpt = (repeatedWallTime == WALLTIME_FIRST) ? BasicTimeZone.LOCAL_FORMER : BasicTimeZone.LOCAL_LATTER;
-            int nonExistingTimeOpt = (skippedWallTime == WALLTIME_FIRST) ? BasicTimeZone.LOCAL_LATTER : BasicTimeZone.LOCAL_FORMER;
+            LocalOption nonExistingTimeOpt = (skippedWallTime == WALLTIME_FIRST) ? LocalOption.LATTER : LocalOption.FORMER;
+            LocalOption duplicatedTimeOpt = (repeatedWallTime == WALLTIME_FIRST) ? LocalOption.FORMER : LocalOption.LATTER;
             ((BasicTimeZone)zone).getOffsetFromLocal(wall, nonExistingTimeOpt, duplicatedTimeOpt, offsets);
         } else {
             // By default, TimeZone#getOffset behaves WALLTIME_LAST for both.
@@ -5778,8 +5779,8 @@
         int[] offsets = new int[2];
         long wall = millis + millisInDay;
         if (zone instanceof BasicTimeZone) {
-            int duplicatedTimeOpt = (repeatedWallTime == WALLTIME_FIRST) ? BasicTimeZone.LOCAL_FORMER : BasicTimeZone.LOCAL_LATTER;
-            int nonExistingTimeOpt = (skippedWallTime == WALLTIME_FIRST) ? BasicTimeZone.LOCAL_LATTER : BasicTimeZone.LOCAL_FORMER;
+            LocalOption nonExistingTimeOpt = (skippedWallTime == WALLTIME_FIRST) ? LocalOption.LATTER : LocalOption.FORMER;
+            LocalOption duplicatedTimeOpt = (repeatedWallTime == WALLTIME_FIRST) ? LocalOption.FORMER : LocalOption.LATTER;
             ((BasicTimeZone)zone).getOffsetFromLocal(wall, nonExistingTimeOpt, duplicatedTimeOpt, offsets);
         } else {
             // By default, TimeZone#getOffset behaves WALLTIME_LAST for both.
diff --git a/icu4j/main/classes/core/src/com/ibm/icu/util/RuleBasedTimeZone.java b/icu4j/main/classes/core/src/com/ibm/icu/util/RuleBasedTimeZone.java
index 5e1d35a..6671562 100644
--- a/icu4j/main/classes/core/src/com/ibm/icu/util/RuleBasedTimeZone.java
+++ b/icu4j/main/classes/core/src/com/ibm/icu/util/RuleBasedTimeZone.java
@@ -17,9 +17,9 @@
 /**
  * <code>RuleBasedTimeZone</code> is a concrete subclass of <code>TimeZone</code> that allows users to define
  * custom historic time transition rules.
- * 
+ *
  * @see com.ibm.icu.util.TimeZoneRule
- * 
+ *
  * @stable ICU 3.8
  */
 public class RuleBasedTimeZone extends BasicTimeZone {
@@ -36,10 +36,10 @@
     /**
      * Constructs a <code>RuleBasedTimeZone</code> object with the ID and the
      * <code>InitialTimeZoneRule</code>
-     * 
+     *
      * @param id                The time zone ID.
      * @param initialRule       The initial time zone rule.
-     * 
+     *
      * @stable ICU 3.8
      */
     public RuleBasedTimeZone(String id, InitialTimeZoneRule initialRule) {
@@ -52,9 +52,9 @@
      * The <code>TimeZoneRule</code> must have start times, that is, the result
      * of {@link com.ibm.icu.util.TimeZoneRule#isTransitionRule()} must be true.
      * Otherwise, <code>IllegalArgumentException</code> is thrown.
-     * 
+     *
      * @param rule The <code>TimeZoneRule</code>.
-     * 
+     *
      * @stable ICU 3.8
      */
     public void addTransitionRule(TimeZoneRule rule) {
@@ -77,9 +77,9 @@
                 throw new IllegalStateException("Too many final rules");
             }
         } else {
-            // If this is not a final rule, add it to the historic rule list 
+            // If this is not a final rule, add it to the historic rule list
             if (historicRules == null) {
-                historicRules = new ArrayList<TimeZoneRule>();
+                historicRules = new ArrayList<>();
             }
             historicRules.add(rule);
         }
@@ -90,7 +90,7 @@
 
     /**
      * {@inheritDoc}
-     * 
+     *
      * @stable ICU 3.8
      */
     @Override
@@ -108,7 +108,7 @@
 
     /**
      * {@inheritDoc}
-     * 
+     *
      * @stable ICU 3.8
      */
     @Override
@@ -118,19 +118,20 @@
 
     /**
      * {@inheritDoc}
-     * @internal
-     * @deprecated This API is ICU internal only.
+     * @draft ICU 69
+     * @provisional This API might change or be removed in a future release.
      */
-    @Deprecated
     @Override
     public void getOffsetFromLocal(long date,
-            int nonExistingTimeOpt, int duplicatedTimeOpt, int[] offsets) {
-        getOffset(date, true, nonExistingTimeOpt, duplicatedTimeOpt, offsets);
+            LocalOption nonExistingTimeOpt, LocalOption duplicatedTimeOpt, int[] offsets) {
+        int nonExistingTimeOptVal = getLocalOptionValue(nonExistingTimeOpt);
+        int duplicatedTimeOptVal = getLocalOptionValue(duplicatedTimeOpt);
+        getOffset(date, true, nonExistingTimeOptVal, duplicatedTimeOptVal, offsets);
     }
-    
+
     /**
      * {@inheritDoc}
-     * 
+     *
      * @stable ICU 3.8
      */
     @Override
@@ -145,7 +146,7 @@
 
     /**
      * {@inheritDoc}
-     * 
+     *
      * @stable ICU 3.8
      */
     @Override
@@ -157,7 +158,7 @@
 
     /**
      * {@inheritDoc}
-     * 
+     *
      * @stable ICU 3.8
      */
     @Override
@@ -170,7 +171,7 @@
 
     /**
      * {@inheritDoc}
-     * 
+     *
      * @stable ICU 3.8
      */
     @Override
@@ -238,7 +239,7 @@
 
     /**
      * {@inheritDoc}
-     * 
+     *
      * @stable ICU 3.8
      */
     @Override
@@ -267,7 +268,7 @@
                 if (finalRules[i] != null && otherRBTZ.finalRules[i] != null
                         && finalRules[i].isEquivalentTo(otherRBTZ.finalRules[i])) {
                     continue;
-                    
+
                 }
                 return false;
             }
@@ -302,7 +303,7 @@
 
     /**
      * {@inheritDoc}
-     * 
+     *
      * @stable ICU 3.8
      */
     @Override
@@ -321,7 +322,7 @@
         }
         TimeZoneRule[] rules = new TimeZoneRule[size];
         rules[0] = initialRule;
-        
+
         int idx = 1;
         if (historicRules != null) {
             for (; idx < historicRules.size() + 1; idx++) {
@@ -339,7 +340,7 @@
 
     /**
      * {@inheritDoc}
-     * 
+     *
      * @stable ICU 3.8
      */
     @Override
@@ -355,7 +356,7 @@
         if (tt > base || (inclusive && tt == base)) {
             result = tzt;
         } else {
-            int idx = historicTransitions.size() - 1;        
+            int idx = historicTransitions.size() - 1;
             tzt = historicTransitions.get(idx);
             tt = tzt.getTime();
             if (inclusive && tt == base) {
@@ -411,7 +412,7 @@
 
     /**
      * {@inheritDoc}
-     * 
+     *
      * @stable ICU 3.8
      */
     @Override
@@ -428,7 +429,7 @@
         } else if (tt >= base) {
             return null;
         } else {
-            int idx = historicTransitions.size() - 1;        
+            int idx = historicTransitions.size() - 1;
             tzt = historicTransitions.get(idx);
             tt = tzt.getTime();
             if (inclusive && tt == base) {
@@ -459,7 +460,7 @@
                     }
                     idx--;
                 }
-                result = tzt;                
+                result = tzt;
             }
         }
         // For now, this implementation ignore transitions with only zone name changes.
@@ -472,7 +473,7 @@
         }
         return result;
     }
-    
+
     /**
      * {@inheritDoc}
      * @stable ICU 3.8
@@ -582,7 +583,7 @@
                     }
 
                     if (historicTransitions == null) {
-                        historicTransitions = new ArrayList<TimeZoneTransition>();
+                        historicTransitions = new ArrayList<>();
                     }
                     historicTransitions.add(new TimeZoneTransition(nextTransitionTime, curRule, nextRule));
                     lastTransitionTime = nextTransitionTime;
@@ -591,7 +592,7 @@
             }
             if (finalRules != null) {
                 if (historicTransitions == null) {
-                    historicTransitions = new ArrayList<TimeZoneTransition>();
+                    historicTransitions = new ArrayList<>();
                 }
                 // Append the first transition for each
                 Date d0 = finalRules[0].getNextStart(lastTransitionTime, curRule.getRawOffset(), curRule.getDSTSavings(), false);
@@ -652,7 +653,7 @@
         offsets[0] = rule.getRawOffset();
         offsets[1] = rule.getDSTSavings();
     }
-    
+
     /*
      * Find a time zone rule applicable to the specified time
      */
@@ -764,6 +765,7 @@
      * {@inheritDoc}
      * @stable ICU 49
      */
+    @Override
     public boolean isFrozen() {
         return isFrozen;
     }
@@ -772,6 +774,7 @@
      * {@inheritDoc}
      * @stable ICU 49
      */
+    @Override
     public TimeZone freeze() {
         complete();
         isFrozen = true;
@@ -782,10 +785,11 @@
      * {@inheritDoc}
      * @stable ICU 49
      */
+    @Override
     public TimeZone cloneAsThawed() {
         RuleBasedTimeZone tz = (RuleBasedTimeZone)super.cloneAsThawed();
         if (historicRules != null) {
-            tz.historicRules = new ArrayList<TimeZoneRule>(historicRules); // rules are immutable
+            tz.historicRules = new ArrayList<>(historicRules); // rules are immutable
         }
         if (finalRules != null) {
             tz.finalRules = finalRules.clone();
@@ -794,4 +798,3 @@
         return tz;
     }
 }
-
diff --git a/icu4j/main/classes/core/src/com/ibm/icu/util/SimpleTimeZone.java b/icu4j/main/classes/core/src/com/ibm/icu/util/SimpleTimeZone.java
index 3779e54..ff717b3 100644
--- a/icu4j/main/classes/core/src/com/ibm/icu/util/SimpleTimeZone.java
+++ b/icu4j/main/classes/core/src/com/ibm/icu/util/SimpleTimeZone.java
@@ -790,13 +790,15 @@
 
     /**
      * {@inheritDoc}
-     * @internal
-     * @deprecated This API is ICU internal only.
+     * @draft ICU 69
+     * @provisional This API might change or be removed in a future release.
      */
     @Override
-    @Deprecated
     public void getOffsetFromLocal(long date,
-            int nonExistingTimeOpt, int duplicatedTimeOpt, int[] offsets) {
+            LocalOption nonExistingTimeOpt, LocalOption duplicatedTimeOpt, int[] offsets) {
+        int nonExistingTimeOptVal = getLocalOptionValue(nonExistingTimeOpt);
+        int duplicatedTimeOptVal = getLocalOptionValue(duplicatedTimeOpt);
+
         offsets[0] = getRawOffset();
         int fields[] = new int[6];
         Grego.timeToFields(date, fields);
@@ -808,16 +810,16 @@
 
         // Now, we need some adjustment
         if (offsets[1] > 0) {
-            if ((nonExistingTimeOpt & STD_DST_MASK) == LOCAL_STD
-                || (nonExistingTimeOpt & STD_DST_MASK) != LOCAL_DST
-                && (nonExistingTimeOpt & FORMER_LATTER_MASK) != LOCAL_LATTER) {
+            if ((nonExistingTimeOptVal & STD_DST_MASK) == LOCAL_STD
+                || (nonExistingTimeOptVal & STD_DST_MASK) != LOCAL_DST
+                && (nonExistingTimeOptVal & FORMER_LATTER_MASK) != LOCAL_LATTER) {
                 date -= getDSTSavings();
                 recalc = true;
             }
         } else {
-            if ((duplicatedTimeOpt & STD_DST_MASK) == LOCAL_DST
-                || (duplicatedTimeOpt & STD_DST_MASK) != LOCAL_STD
-                && (duplicatedTimeOpt & FORMER_LATTER_MASK) == LOCAL_FORMER) {
+            if ((duplicatedTimeOptVal & STD_DST_MASK) == LOCAL_DST
+                || (duplicatedTimeOptVal & STD_DST_MASK) != LOCAL_STD
+                && (duplicatedTimeOptVal & FORMER_LATTER_MASK) == LOCAL_FORMER) {
                 date -= getDSTSavings();
                 recalc = true;
             }
@@ -1448,4 +1450,4 @@
         tz.isFrozen = false;
         return tz;
     }
-}
+}
\ No newline at end of file
diff --git a/icu4j/main/classes/core/src/com/ibm/icu/util/VTimeZone.java b/icu4j/main/classes/core/src/com/ibm/icu/util/VTimeZone.java
index 0282754..c616de8 100644
--- a/icu4j/main/classes/core/src/com/ibm/icu/util/VTimeZone.java
+++ b/icu4j/main/classes/core/src/com/ibm/icu/util/VTimeZone.java
@@ -28,11 +28,11 @@
  * in RFC2445 VTIMEZONE format.  Also, you can create a <code>VTimeZone</code> instance
  * from RFC2445 VTIMEZONE data stream, which allows you to calculate time
  * zone offset by the rules defined by the data.<br><br>
- * 
+ *
  * Note: The consumer of this class reading or writing VTIMEZONE data is responsible to
  * decode or encode Non-ASCII text.  Methods reading/writing VTIMEZONE data in this class
  * do nothing with MIME encoding.
- * 
+ *
  * @stable ICU 3.8
  */
 public class VTimeZone extends BasicTimeZone {
@@ -41,11 +41,11 @@
 
     /**
      * Create a <code>VTimeZone</code> instance by the time zone ID.
-     * 
+     *
      * @param tzid The time zone ID, such as America/New_York
      * @return A <code>VTimeZone</code> initialized by the time zone ID, or null
      * when the ID is unknown.
-     * 
+     *
      * @stable ICU 3.8
      */
     public static VTimeZone create(String tzid) {
@@ -59,14 +59,14 @@
 
         return vtz;
     }
-    
+
     /**
      * Create a <code>VTimeZone</code> instance by RFC2445 VTIMEZONE data.
-     * 
+     *
      * @param reader The Reader for VTIMEZONE data input stream
      * @return A <code>VTimeZone</code> initialized by the VTIMEZONE data or
      * null if failed to load the rule from the VTIMEZONE data.
-     * 
+     *
      * @stable ICU 3.8
      */
     public static VTimeZone create(Reader reader) {
@@ -98,13 +98,12 @@
 
     /**
      * {@inheritDoc}
-     * @internal
-     * @deprecated This API is ICU internal only.
+     * @draft ICU 69
+     * @provisional This API might change or be removed in a future release.
      */
-    @Deprecated
     @Override
     public void getOffsetFromLocal(long date,
-            int nonExistingTimeOpt, int duplicatedTimeOpt, int[] offsets) {
+            LocalOption nonExistingTimeOpt, LocalOption duplicatedTimeOpt, int[] offsets) {
         tz.getOffsetFromLocal(date, nonExistingTimeOpt, duplicatedTimeOpt, offsets);
     }
 
@@ -175,9 +174,9 @@
      * Gets the RFC2445 TZURL property value.  When a <code>VTimeZone</code> instance was created from
      * VTIMEZONE data, the value is set by the TZURL property value in the data.  Otherwise,
      * the initial value is null.
-     * 
+     *
      * @return The RFC2445 TZURL property value
-     * 
+     *
      * @stable ICU 3.8
      */
     public String getTZURL() {
@@ -186,9 +185,9 @@
 
     /**
      * Sets the RFC2445 TZURL property value.
-     * 
+     *
      * @param url The TZURL property value.
-     * 
+     *
      * @stable ICU 3.8
      */
     public void setTZURL(String url) {
@@ -202,9 +201,9 @@
      * Gets the RFC2445 LAST-MODIFIED property value.  When a <code>VTimeZone</code> instance was created
      * from VTIMEZONE data, the value is set by the LAST-MODIFIED property value in the data.
      * Otherwise, the initial value is null.
-     * 
+     *
      * @return The Date represents the RFC2445 LAST-MODIFIED date.
-     * 
+     *
      * @stable ICU 3.8
      */
     public Date getLastModified() {
@@ -213,9 +212,9 @@
 
     /**
      * Sets the date used for RFC2445 LAST-MODIFIED property value.
-     * 
+     *
      * @param date The <code>Date</code> object represents the date for RFC2445 LAST-MODIFIED property value.
-     * 
+     *
      * @stable ICU 3.8
      */
     public void setLastModified(Date date) {
@@ -227,10 +226,10 @@
 
     /**
      * Writes RFC2445 VTIMEZONE data for this time zone
-     * 
+     *
      * @param writer A <code>Writer</code> used for the output
      * @throws IOException If there were problems creating a buffered writer or writing to it.
-     * 
+     *
      * @stable ICU 3.8
      */
     public void write(Writer writer) throws IOException {
@@ -270,12 +269,12 @@
     /**
      * Writes RFC2445 VTIMEZONE data applicable for dates after
      * the specified start time.
-     * 
+     *
      * @param writer    The <code>Writer</code> used for the output
      * @param start     The start time
-     * 
+     *
      * @throws IOException If there were problems reading and writing to the writer.
-     * 
+     *
      * @stable ICU 3.8
      */
     public void write(Writer writer, long start) throws IOException {
@@ -290,7 +289,7 @@
         String[] customProperties = null;
         if (olsonzid != null && ICU_TZVERSION != null) {
             customProperties = new String[1];
-            customProperties[0] = ICU_TZINFO_PROP + COLON + olsonzid + "[" + ICU_TZVERSION + 
+            customProperties[0] = ICU_TZINFO_PROP + COLON + olsonzid + "[" + ICU_TZVERSION +
                 "/Partial@" + start + "]";
         }
         writeZone(writer, rbtz, customProperties);
@@ -304,12 +303,12 @@
      * the VTIMEZONE data which can be handled these implementations.  The rules
      * produced by this method can be used only for calculating time zone offset
      * around the specified date.
-     * 
+     *
      * @param writer    The <code>Writer</code> used for the output
      * @param time      The date
-     * 
+     *
      * @throws IOException If there were problems reading or writing to the writer.
-     * 
+     *
      * @stable ICU 3.8
      */
     public void writeSimple(Writer writer, long time) throws IOException {
@@ -324,7 +323,7 @@
         String[] customProperties = null;
         if (olsonzid != null && ICU_TZVERSION != null) {
             customProperties = new String[1];
-            customProperties[0] = ICU_TZINFO_PROP + COLON + olsonzid + "[" + ICU_TZVERSION + 
+            customProperties[0] = ICU_TZINFO_PROP + COLON + olsonzid + "[" + ICU_TZVERSION +
                 "/Simple@" + time + "]";
         }
         writeZone(writer, rbtz, customProperties);
@@ -405,7 +404,7 @@
 
     // Default DST savings
     private static final int DEF_DSTSAVINGS = 60*60*1000; // 1 hour
-    
+
     // Default time start
     private static final long DEF_TZSTARTTIME = 0;
 
@@ -445,7 +444,7 @@
     private static final String ICAL_BYDAY = "BYDAY";
     private static final String ICAL_BYMONTHDAY = "BYMONTHDAY";
 
-    private static final String[] ICAL_DOW_NAMES = 
+    private static final String[] ICAL_DOW_NAMES =
     {"SU", "MO", "TU", "WE", "TH", "FR", "SA"};
 
     // Month length in regular year
@@ -461,7 +460,7 @@
             ///CLOVER:ON
         }
     }
-    
+
     /* Hide the constructor */
     private VTimeZone() {
     }
@@ -483,7 +482,7 @@
     private boolean load(Reader reader) {
         // Read VTIMEZONE block into string array
         try {
-            vtzlines = new LinkedList<String>();
+            vtzlines = new LinkedList<>();
             boolean eol = false;
             boolean start = false;
             boolean success = false;
@@ -578,7 +577,7 @@
         String dtstart = null;  // current zone starts
         boolean isRRULE = false;    // true if the rule is described by RRULE
         List<String> dates = null;  // list of RDATE or RRULE strings
-        List<TimeZoneRule> rules = new ArrayList<TimeZoneRule>();   // rule list
+        List<TimeZoneRule> rules = new ArrayList<>();   // rule list
         int initialRawOffset = 0;  // initial offset
         int initialDSTSavings = 0;  // initial offset
         long firstStart = MAX_TIME; // the earliest rule start time
@@ -649,7 +648,7 @@
                         break;
                     }
                     if (dates == null) {
-                        dates = new LinkedList<String>();
+                        dates = new LinkedList<>();
                     }
                     // RDATE value may contain multiple date delimited
                     // by comma
@@ -664,7 +663,7 @@
                         state = ERR;
                         break;
                     } else if (dates == null) {
-                        dates = new LinkedList<String>();
+                        dates = new LinkedList<>();
                     }
                     isRRULE = true;
                     dates.add(value);
@@ -699,7 +698,7 @@
                             } else {
                                 // This is rare case..  just use 1 hour DST savings
                                 rawOffset = toOffset - DEF_DSTSAVINGS;
-                                dstSavings = DEF_DSTSAVINGS;                                
+                                dstSavings = DEF_DSTSAVINGS;
                             }
                         } else {
                             rawOffset = toOffset;
@@ -797,7 +796,7 @@
                 AnnualTimeZoneRule finalRule = (AnnualTimeZoneRule)rules.get(finalRuleIdx);
                 int tmpRaw = finalRule.getRawOffset();
                 int tmpDST = finalRule.getDSTSavings();
-    
+
                 // Find the last non-final rule
                 Date finalStart = finalRule.getFirstStart(initialRawOffset, initialDSTSavings);
                 Date start = finalStart;
@@ -953,7 +952,7 @@
                 if (unt[0] > until[0]) {
                     until = unt;
                 }
-                
+
                 // Check if BYMONTH + BYMONTHDAY + BYDAY rule
                 if (fields[0] == -1 || fields[1] == 0 || fields[3] == 0) {
                     return null;
@@ -1050,18 +1049,18 @@
 
     /*
      * Parse individual RRULE
-     * 
+     *
      * On return -
-     * 
+     *
      * int[0] month calculated by BYMONTH - 1, or -1 when not found
      * int[1] day of week in BYDAY, or 0 when not found
      * int[2] day of week ordinal number in BYDAY, or 0 when not found
      * int[i >= 3] day of month, which could be multiple values, or 0 when not found
-     * 
+     *
      *  or
-     * 
+     *
      * null on any error cases, for exmaple, FREQ=YEARLY is not available
-     * 
+     *
      * When UNTIL attribute is available, the time will be set to until[0],
      * otherwise, MIN_TIME
      */
@@ -1094,7 +1093,7 @@
                     yearly = true;
                 } else {
                     parseError = true;
-                    break;                        
+                    break;
                 }
             } else if (attr.equals(ICAL_UNTIL)) {
                 // ISO8601 UTC format, for example, "20060315T020000Z"
@@ -1214,7 +1213,7 @@
         results[2] = nthDayOfWeek;
         return results;
     }
-    
+
     /*
      * Create a TimeZoneRule by the RDATE definition
      */
@@ -1335,7 +1334,7 @@
                                     dstMonth, dstWeekInMonth, dstDayOfWeek, dstStartTime, dstUntilTime);
                         }
                     }
-                } 
+                }
                 if (!sameRule) {
                     // Reset this DST information
                     dstName = name;
@@ -1407,7 +1406,7 @@
             int offset = basictz.getOffset(0 /* any time */);
             boolean isDst = (offset != basictz.getRawOffset());
             writeZonePropsByTime(w, isDst, getDefaultTZName(basictz.getID(), isDst),
-                    offset, offset, DEF_TZSTARTTIME - offset, false);                
+                    offset, offset, DEF_TZSTARTTIME - offset, false);
         } else {
             if (dstCount > 0) {
                 if (finalDstRule == null) {
@@ -1474,12 +1473,12 @@
                             if (nextStart != null) {
                                 writeFinalRule(w, false, finalStdRule,
                                         stdFromOffset - stdFromDSTSavings, stdFromDSTSavings, nextStart.getTime());
-                                
+
                             }
                         }
                     }
                 }
-            }            
+            }
         }
         writeFooter(w);
     }
@@ -1599,7 +1598,7 @@
             // Check if all days are in the same month
             int startDay = dayOfMonth;
             int currentMonthDays = 7;
-        
+
             if (dayOfMonth <= 0) {
                 // The start day is in previous month
                 int prevMonthDays = 1 - dayOfMonth;
@@ -1621,14 +1620,14 @@
                 currentMonthDays -= nextMonthDays;
 
                 int nextMonth = (month + 1) > 11 ? 0 : month + 1;
-                
+
                 writeZonePropsByDOW_GEQ_DOM_sub(writer, nextMonth, 1, dayOfWeek, nextMonthDays, MAX_TIME /* Do not use UNTIL */, fromOffset);
             }
             writeZonePropsByDOW_GEQ_DOM_sub(writer, month, startDay, dayOfWeek, currentMonthDays, untilTime, fromOffset);
             endZoneProps(writer, isDst);
         }
     }
- 
+
     /*
      * Called from writeZonePropsByDOW_GEQ_DOM
      */
@@ -1829,12 +1828,12 @@
         writer.write(COLON);
         writer.write(tzname);
         writer.write(NEWLINE);
-        
+
         // DTSTART
         writer.write(ICAL_DTSTART);
         writer.write(COLON);
         writer.write(getDateTimeString(startTime + fromOffset));
-        writer.write(NEWLINE);        
+        writer.write(NEWLINE);
     }
 
     /*
@@ -1933,7 +1932,7 @@
         int min = t / Grego.MILLIS_PER_MINUTE;
         t %= Grego.MILLIS_PER_MINUTE;
         int sec = t / Grego.MILLIS_PER_SECOND;
-        
+
         sb.append(numToString(hour, 2));
         sb.append(numToString(min, 2));
         sb.append(numToString(sec, 2));
@@ -2107,6 +2106,7 @@
      * {@inheritDoc}
      * @stable ICU 49
      */
+    @Override
     public boolean isFrozen() {
         return isFrozen;
     }
@@ -2115,6 +2115,7 @@
      * {@inheritDoc}
      * @stable ICU 49
      */
+    @Override
     public TimeZone freeze() {
         isFrozen = true;
         return this;
@@ -2124,6 +2125,7 @@
      * {@inheritDoc}
      * @stable ICU 49
      */
+    @Override
     public TimeZone cloneAsThawed() {
         VTimeZone vtz = (VTimeZone)super.cloneAsThawed();
         vtz.tz = (BasicTimeZone)tz.cloneAsThawed();
diff --git a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/timezone/TimeZoneOffsetLocalTest.java b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/timezone/TimeZoneOffsetLocalTest.java
index 6b8d981..55acc68 100644
--- a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/timezone/TimeZoneOffsetLocalTest.java
+++ b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/timezone/TimeZoneOffsetLocalTest.java
@@ -18,6 +18,7 @@
 import com.ibm.icu.text.DateFormat;
 import com.ibm.icu.util.AnnualTimeZoneRule;
 import com.ibm.icu.util.BasicTimeZone;
+import com.ibm.icu.util.BasicTimeZone.LocalOption;
 import com.ibm.icu.util.Calendar;
 import com.ibm.icu.util.DateTimeRule;
 import com.ibm.icu.util.GregorianCalendar;
@@ -71,8 +72,8 @@
 
 
         // Expected offsets by getOffset(long time, boolean local, int[] offsets) with local = true
-        // or getOffsetFromLocal(long time, int nonExistingTimeOpt, int duplicatedTimeOpt, int[] offsets)
-        // with nonExistingTimeOpt = LOCAL_STD/duplicatedTimeOpt = LOCAL_STD
+        // or getOffsetFromLocal(long time, LocalOption nonExistingTimeOpt, LocalOption duplicatedTimeOpt, int[] offsets)
+        // with nonExistingTimeOpt = STANDARD_*/duplicatedTimeOpt = STANDARD_*
         int[][] OFFSETS2 = {
             // April 2, 2006
             {-8*HOUR, 0},
@@ -89,8 +90,8 @@
             {-8*HOUR, 0},
         };
 
-        // Expected offsets by getOffsetFromLocal(long time, int nonExistingTimeOpt, int duplicatedTimeOpt, int[] offsets)
-        // with nonExistingTimeOpt = LOCAL_DST/duplicatedTimeOpt = LOCAL_DST
+        // Expected offsets by getOffsetFromLocal(long time, LocalOption nonExistingTimeOpt, LocalOption duplicatedTimeOpt, int[] offsets)
+        // with nonExistingTimeOpt = DAYLIGHT_*/duplicatedTimeOpt = DAYLIGHT_*
         int[][] OFFSETS3 = {
             // April 2, 2006
             {-8*HOUR, 0},
@@ -184,39 +185,39 @@
             }
         }
 
-        // Test getOffsetFromLocal(long time, int nonExistingTimeOpt, int duplicatedTimeOpt, int[] offsets)
-        // with nonExistingTimeOpt = LOCAL_STD/duplicatedTimeOpt = LOCAL_STD
+        // Test getOffsetFromLocal(long time, LocalOption nonExistingTimeOpt, LocalOption duplicatedTimeOpt, int[] offsets)
+        // with nonExistingTimeOpt = STANDARD_*/duplicatedTimeOpt = STANDARD_*
         for (int i = 0; i < TESTZONES.length; i++) {
             for (int m = 0; m < MILLIS.length; m++) {
-                TESTZONES[i].getOffsetFromLocal(MILLIS[m], BasicTimeZone.LOCAL_STD, BasicTimeZone.LOCAL_STD, offsets);
+                TESTZONES[i].getOffsetFromLocal(MILLIS[m], LocalOption.STANDARD_FORMER, LocalOption.STANDARD_LATTER, offsets);
                 if (offsets[0] != OFFSETS2[m][0] || offsets[1] != OFFSETS2[m][1]) {
                     errln("Bad offset returned by " + TESTZONES[i].getID() + " at "
-                            + df.format(new Date(MILLIS[m])) + "(wall/STD/STD) - Got: "
+                            + df.format(new Date(MILLIS[m])) + "(wall/STANDARD_FORMER/STANDARD_LATTER) - Got: "
                             + offsets[0] + "/" + offsets[1]
                             + " Expected: " + OFFSETS2[m][0] + "/" + OFFSETS2[m][1]);
                 }
             }
         }
 
-        // Test getOffsetFromLocal(long time, int nonExistingTimeOpt, int duplicatedTimeOpt, int[] offsets)
-        // with nonExistingTimeOpt = LOCAL_DST/duplicatedTimeOpt = LOCAL_DST
+        // Test getOffsetFromLocal(long time, LocalOption nonExistingTimeOpt, LocalOption duplicatedTimeOpt, int[] offsets)
+        // with nonExistingTimeOpt = DAYLIGHT_*/duplicatedTimeOpt = DAYLIGHT_*
         for (int i = 0; i < TESTZONES.length; i++) {
             for (int m = 0; m < MILLIS.length; m++) {
-                TESTZONES[i].getOffsetFromLocal(MILLIS[m], BasicTimeZone.LOCAL_DST, BasicTimeZone.LOCAL_DST, offsets);
+                TESTZONES[i].getOffsetFromLocal(MILLIS[m], LocalOption.DAYLIGHT_LATTER, LocalOption.DAYLIGHT_FORMER, offsets);
                 if (offsets[0] != OFFSETS3[m][0] || offsets[1] != OFFSETS3[m][1]) {
                     errln("Bad offset returned by " + TESTZONES[i].getID() + " at "
-                            + df.format(new Date(MILLIS[m])) + "(wall/DST/DST) - Got: "
+                            + df.format(new Date(MILLIS[m])) + "(wall/DAYLIGHT_LATTER/DAYLIGHT_FORMER) - Got: "
                             + offsets[0] + "/" + offsets[1]
                             + " Expected: " + OFFSETS3[m][0] + "/" + OFFSETS3[m][1]);
                 }
             }
         }
 
-        // Test getOffsetFromLocal(long time, int nonExistingTimeOpt, int duplicatedTimeOpt, int[] offsets)
-        // with nonExistingTimeOpt = LOCAL_FORMER/duplicatedTimeOpt = LOCAL_LATTER
+        // Test getOffsetFromLocal(long time, LocalOption nonExistingTimeOpt, LocalOption duplicatedTimeOpt, int[] offsets)
+        // with nonExistingTimeOpt = FORMER/duplicatedTimeOpt = LATTER
         for (int i = 0; i < TESTZONES.length; i++) {
             for (int m = 0; m < MILLIS.length; m++) {
-                TESTZONES[i].getOffsetFromLocal(MILLIS[m], BasicTimeZone.LOCAL_FORMER, BasicTimeZone.LOCAL_LATTER, offsets);
+                TESTZONES[i].getOffsetFromLocal(MILLIS[m], LocalOption.FORMER, LocalOption.LATTER, offsets);
                 if (offsets[0] != OFFSETS2[m][0] || offsets[1] != OFFSETS2[m][1]) {
                     errln("Bad offset returned by " + TESTZONES[i].getID() + " at "
                             + df.format(new Date(MILLIS[m])) + "(wall/FORMER/LATTER) - Got: "
@@ -226,11 +227,11 @@
             }
         }
 
-        // Test getOffsetFromLocal(long time, int nonExistingTimeOpt, int duplicatedTimeOpt, int[] offsets)
-        // with nonExistingTimeOpt = LOCAL_LATTER/duplicatedTimeOpt = LOCAL_FORMER
+        // Test getOffsetFromLocal(long time, LocalOption nonExistingTimeOpt, LocalOption duplicatedTimeOpt, int[] offsets)
+        // with nonExistingTimeOpt = LATTER/duplicatedTimeOpt = FORMER
         for (int i = 0; i < TESTZONES.length; i++) {
             for (int m = 0; m < MILLIS.length; m++) {
-                TESTZONES[i].getOffsetFromLocal(MILLIS[m], BasicTimeZone.LOCAL_LATTER, BasicTimeZone.LOCAL_FORMER, offsets);
+                TESTZONES[i].getOffsetFromLocal(MILLIS[m], LocalOption.LATTER, LocalOption.FORMER, offsets);
                 if (offsets[0] != OFFSETS3[m][0] || offsets[1] != OFFSETS3[m][1]) {
                     errln("Bad offset returned by " + TESTZONES[i].getID() + " at "
                             + df.format(new Date(MILLIS[m])) + "(wall/LATTER/FORMER) - Got: "
diff --git a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/timezone/TimeZoneRuleTest.java b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/timezone/TimeZoneRuleTest.java
index 34c4e3b..08df3fb 100644
--- a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/timezone/TimeZoneRuleTest.java
+++ b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/timezone/TimeZoneRuleTest.java
@@ -24,6 +24,7 @@
 import com.ibm.icu.dev.test.TestFmwk;
 import com.ibm.icu.util.AnnualTimeZoneRule;
 import com.ibm.icu.util.BasicTimeZone;
+import com.ibm.icu.util.BasicTimeZone.LocalOption;
 import com.ibm.icu.util.Calendar;
 import com.ibm.icu.util.DateTimeRule;
 import com.ibm.icu.util.GregorianCalendar;
@@ -1235,7 +1236,7 @@
 
         int[] offsets_vtzc = new int[2];
         VTimeZone vtzc = VTimeZone.create("PST");
-        vtzc.getOffsetFromLocal(Calendar.getInstance(vtzc).getTimeInMillis(), VTimeZone.LOCAL_STD, VTimeZone.LOCAL_STD, offsets_vtzc);
+        vtzc.getOffsetFromLocal(Calendar.getInstance(vtzc).getTimeInMillis(), LocalOption.STANDARD_FORMER, LocalOption.STANDARD_LATTER, offsets_vtzc);
         if (offsets_vtzc[0] > offsets_vtzc[1]) {
             errln("Error getOffsetFromLocal()");
         }
@@ -1469,7 +1470,7 @@
             BasicTimeZone btz = (BasicTimeZone)tz;
             int []offsets = new int[2];
 
-            btz.getOffsetFromLocal(Calendar.getInstance().getTimeInMillis(), BasicTimeZone.LOCAL_STD, BasicTimeZone.LOCAL_STD, offsets);
+            btz.getOffsetFromLocal(Calendar.getInstance().getTimeInMillis(), LocalOption.STANDARD_FORMER, LocalOption.STANDARD_LATTER, offsets);
             if (offsets[0] > offsets[1]) {
                 errln("Error calling getOffsetFromLocal().");
             }