1/* GENERATED SOURCE. DO NOT MODIFY. */
2/*
3 *******************************************************************************
4 * Copyright (C) 2007-2014, International Business Machines Corporation and    *
5 * others. All Rights Reserved.                                                *
6 *******************************************************************************
7 */
8package android.icu.util;
9
10import java.util.BitSet;
11import java.util.Date;
12import java.util.LinkedList;
13import java.util.List;
14
15import android.icu.impl.Grego;
16
17/**
18 * <strong>[icu]</strong> BasicTimeZone extends <code>TimeZone</code> with additional methods to access
19 * time zone transitions and rules.  All ICU <code>TimeZone</code> concrete subclasses
20 * extend this class. APIs added to <code>java.util.TimeZone</code> by
21 * <code>BasicTimeZone</code> are annotated with <strong>'<font
22 * style="color:red">[icu]</font>'</strong>.
23 *
24 * @see android.icu.util.TimeZoneRule
25 * @see android.icu.util.TimeZoneTransition
26 *
27 * @hide Only a subset of ICU is exposed in Android
28 */
29public abstract class BasicTimeZone extends TimeZone {
30
31    private static final long serialVersionUID = -3204278532246180932L;
32
33    private static final long MILLIS_PER_YEAR = 365*24*60*60*1000L;
34
35    /**
36     * <strong>[icu]</strong> Returns the first time zone transition after the base time.
37     * <p>Example code:{{@literal @}.jcite  android.icu.samples.util.timezone.BasicTimeZoneExample:---getNextTransitionExample}
38     *
39     * @param base      The base time.
40     * @param inclusive Whether the base time is inclusive or not.
41     *
42     * @return  A <code>Date</code> holding the first time zone transition time
43     *          after the given base time, or null if no time zone transitions
44     *          are available after the base time.
45     */
46    public abstract TimeZoneTransition getNextTransition(long base, boolean inclusive);
47
48    /**
49     * <strong>[icu]</strong> Returns the last time zone transition before the base time.
50     * <p>Example code:{{@literal @}.jcite  android.icu.samples.util.timezone.BasicTimeZoneExample:---getPreviousTransitionExample}
51     *
52     * @param base      The base time.
53     * @param inclusive Whether the base time is inclusive or not.
54     *
55     * @return  A <code>Date</code> holding the last time zone transition time
56     *          before the given base time, or null if no time zone transitions
57     *          are available before the base time.
58     */
59    public abstract TimeZoneTransition getPreviousTransition(long base, boolean inclusive);
60
61    /**
62     * <strong>[icu]</strong> Checks if the time zone has equivalent transitions in the time range.
63     * This method returns true when all of transition times, from/to standard
64     * offsets and DST savings used by this time zone match the other in the
65     * time range.
66     * <p>Example code:{{@literal @}.jcite  android.icu.samples.util.timezone.BasicTimeZoneExample:---hasEquivalentTransitionsExample}
67     *
68     * @param tz    The instance of <code>TimeZone</code>
69     * @param start The start time of the evaluated time range (inclusive)
70     * @param end   The end time of the evaluated time range (inclusive)
71     *
72     * @return true if the other time zone has the equivalent transitions in the
73     * time range.  When tz is not a <code>BasicTimeZone</code>, this method
74     * returns false.
75     */
76    public boolean hasEquivalentTransitions(TimeZone tz, long start, long end) {
77        return hasEquivalentTransitions(tz, start, end, false);
78    }
79
80    /**
81     * <strong>[icu]</strong> Checks if the time zone has equivalent transitions in the time range.
82     * This method returns true when all of transition times, from/to standard
83     * offsets and DST savings used by this time zone match the other in the
84     * time range.
85     *
86     * @param tz    The instance of <code>TimeZone</code>
87     * @param start The start time of the evaluated time range (inclusive)
88     * @param end   The end time of the evaluated time range (inclusive)
89     * @param ignoreDstAmount When true, any transitions with only daylight saving amount
90     * changes will be ignored, except either of them is zero. For example, a transition
91     * from rawoffset 3:00/dstsavings 1:00 to rawoffset 2:00/dstsavings 2:00 is excluded
92     * from the comparison, but a transtion from rawoffset 2:00/dstsavings 1:00 to
93     * rawoffset 3:00/dstsavings 0:00 is included.
94     *
95     * @return true if the other time zone has the equivalent transitions in the
96     * time range.  When tz is not a <code>BasicTimeZone</code>, this method
97     * returns false.
98     */
99    public boolean hasEquivalentTransitions(TimeZone tz, long start, long end,
100                                            boolean ignoreDstAmount) {
101        if (this == tz) {
102            return true;
103        }
104
105        if (!(tz instanceof BasicTimeZone)) {
106            return false;
107        }
108
109        // Check the offsets at the start time
110        int[] offsets1 = new int[2];
111        int[] offsets2 = new int[2];
112
113        getOffset(start, false, offsets1);
114        tz.getOffset(start, false, offsets2);
115
116        if (ignoreDstAmount) {
117            if ((offsets1[0] + offsets1[1] != offsets2[0] + offsets2[1])
118                || (offsets1[1] != 0 && offsets2[1] == 0)
119                || (offsets1[1] == 0 && offsets2[1] != 0)) {
120                return false;
121            }
122        } else {
123            if (offsets1[0] != offsets2[0] || offsets1[1] != offsets2[1]) {
124                return false;
125            }
126        }
127
128        // Check transitions in the range
129        long time = start;
130        while (true) {
131            TimeZoneTransition tr1 = getNextTransition(time, false);
132            TimeZoneTransition tr2 = ((BasicTimeZone)tz).getNextTransition(time, false);
133
134            if (ignoreDstAmount) {
135                // Skip a transition which only differ the amount of DST savings
136                while (true) {
137                    if (tr1 != null
138                            && tr1.getTime() <= end
139                            && (tr1.getFrom().getRawOffset() + tr1.getFrom().getDSTSavings()
140                                    == tr1.getTo().getRawOffset() + tr1.getTo().getDSTSavings())
141                            && (tr1.getFrom().getDSTSavings() != 0 && tr1.getTo().getDSTSavings() != 0)) {
142                        tr1 = getNextTransition(tr1.getTime(), false);
143                    } else {
144                        break;
145                    }
146                }
147                while (true) {
148                    if (tr2 != null
149                            && tr2.getTime() <= end
150                            && (tr2.getFrom().getRawOffset() + tr2.getFrom().getDSTSavings()
151                                    == tr2.getTo().getRawOffset() + tr2.getTo().getDSTSavings())
152                            && (tr2.getFrom().getDSTSavings() != 0 && tr2.getTo().getDSTSavings() != 0)) {
153                        tr2 = ((BasicTimeZone)tz).getNextTransition(tr2.getTime(), false);
154                    } else {
155                        break;
156                    }
157                }
158            }
159
160            boolean inRange1 = false;
161            boolean inRange2 = false;
162            if (tr1 != null) {
163                if (tr1.getTime() <= end) {
164                    inRange1 = true;
165                }
166            }
167            if (tr2 != null) {
168                if (tr2.getTime() <= end) {
169                    inRange2 = true;
170                }
171            }
172            if (!inRange1 && !inRange2) {
173                // No more transition in the range
174                break;
175            }
176            if (!inRange1 || !inRange2) {
177                return false;
178            }
179            if (tr1.getTime() != tr2.getTime()) {
180                return false;
181            }
182            if (ignoreDstAmount) {
183                if (tr1.getTo().getRawOffset() + tr1.getTo().getDSTSavings()
184                            != tr2.getTo().getRawOffset() + tr2.getTo().getDSTSavings()
185                        || tr1.getTo().getDSTSavings() != 0 &&  tr2.getTo().getDSTSavings() == 0
186                        || tr1.getTo().getDSTSavings() == 0 &&  tr2.getTo().getDSTSavings() != 0) {
187                    return false;
188                }
189            } else {
190                if (tr1.getTo().getRawOffset() != tr2.getTo().getRawOffset() ||
191                    tr1.getTo().getDSTSavings() != tr2.getTo().getDSTSavings()) {
192                    return false;
193                }
194            }
195            time = tr1.getTime();
196        }
197        return true;
198    }
199
200    /**
201     * <strong>[icu]</strong> Returns the array of <code>TimeZoneRule</code> which represents the rule
202     * of this time zone object.  The first element in the result array will
203     * be the <code>InitialTimeZoneRule</code> instance for the initial rule.
204     * The rest will be either <code>AnnualTimeZoneRule</code> or
205     * <code>TimeArrayTimeZoneRule</code> instances representing transitions.
206     *
207     * @return  The array of <code>TimeZoneRule</code> which represents this
208     *          time zone.
209     */
210    public abstract TimeZoneRule[] getTimeZoneRules();
211
212    /**
213     * <strong>[icu]</strong> Returns the array of <code>TimeZoneRule</code> which represents the rule
214     * of this time zone object since the specified start time.  The first
215     * element in the result array will be the <code>InitialTimeZoneRule</code>
216     * instance for the initial rule.  The rest will be either
217     * <code>AnnualTimeZoneRule</code> or <code>TimeArrayTimeZoneRule</code>
218     * instances representing transitions.
219     * <p>Example code:{{@literal @}.jcite  android.icu.samples.util.timezone.BasicTimeZoneExample:---getTimeZoneRulesExample}
220     *
221     * @param start The start time (inclusive).
222     * @return  The array of <code>TimeZoneRule</code> which represents this
223     *          time zone since the start time.
224     */
225    public TimeZoneRule[] getTimeZoneRules(long start) {
226        TimeZoneRule[] all = getTimeZoneRules();
227        TimeZoneTransition tzt = getPreviousTransition(start, true);
228        if (tzt == null) {
229            // No need to filter out rules only applicable to time before the start
230            return all;
231        }
232
233        BitSet isProcessed = new BitSet(all.length);
234        List<TimeZoneRule> filteredRules = new LinkedList<TimeZoneRule>();
235
236        // Create initial rule
237        TimeZoneRule initial = new InitialTimeZoneRule(tzt.getTo().getName(),
238                tzt.getTo().getRawOffset(), tzt.getTo().getDSTSavings());
239        filteredRules.add(initial);
240        isProcessed.set(0);
241
242        // Mark rules which does not need to be processed
243        for (int i = 1; i < all.length; i++) {
244            Date d = all[i].getNextStart(start, initial.getRawOffset(),
245                    initial.getDSTSavings(), false);
246            if (d == null) {
247                isProcessed.set(i);
248            }
249        }
250
251        long time = start;
252        boolean bFinalStd = false, bFinalDst = false;
253        while(!bFinalStd || !bFinalDst) {
254            tzt = getNextTransition(time, false);
255            if (tzt == null) {
256                break;
257            }
258            time = tzt.getTime();
259
260            TimeZoneRule toRule = tzt.getTo();
261            int ruleIdx = 1;
262            for (; ruleIdx < all.length; ruleIdx++) {
263                if (all[ruleIdx].equals(toRule)) {
264                    break;
265                }
266            }
267            if (ruleIdx >= all.length) {
268                throw new IllegalStateException("The rule was not found");
269            }
270            if (isProcessed.get(ruleIdx)) {
271                continue;
272            }
273            if (toRule instanceof TimeArrayTimeZoneRule) {
274                TimeArrayTimeZoneRule tar = (TimeArrayTimeZoneRule)toRule;
275
276                // Get the previous raw offset and DST savings before the very first start time
277                long t = start;
278                while(true) {
279                    tzt = getNextTransition(t, false);
280                    if (tzt == null) {
281                        break;
282                    }
283                    if (tzt.getTo().equals(tar)) {
284                        break;
285                    }
286                    t = tzt.getTime();
287                }
288                if (tzt != null) {
289                    // Check if the entire start times to be added
290                    Date firstStart = tar.getFirstStart(tzt.getFrom().getRawOffset(),
291                            tzt.getFrom().getDSTSavings());
292                    if (firstStart.getTime() > start) {
293                        // Just add the rule as is
294                        filteredRules.add(tar);
295                    } else {
296                        // Collect transitions after the start time
297                        long[] times = tar.getStartTimes();
298                        int timeType = tar.getTimeType();
299                        int idx;
300                        for (idx = 0; idx < times.length; idx++) {
301                            t = times[idx];
302                            if (timeType == DateTimeRule.STANDARD_TIME) {
303                                t -= tzt.getFrom().getRawOffset();
304                            }
305                            if (timeType == DateTimeRule.WALL_TIME) {
306                                t -= tzt.getFrom().getDSTSavings();
307                            }
308                            if (t > start) {
309                                break;
310                            }
311                        }
312                        int asize = times.length - idx;
313                        if (asize > 0) {
314                            long[] newtimes = new long[asize];
315                            System.arraycopy(times, idx, newtimes, 0, asize);
316                            TimeArrayTimeZoneRule newtar = new TimeArrayTimeZoneRule(
317                                    tar.getName(), tar.getRawOffset(), tar.getDSTSavings(),
318                                    newtimes, tar.getTimeType());
319                            filteredRules.add(newtar);
320                        }
321                    }
322                }
323            } else if (toRule instanceof AnnualTimeZoneRule) {
324                AnnualTimeZoneRule ar = (AnnualTimeZoneRule)toRule;
325                Date firstStart = ar.getFirstStart(tzt.getFrom().getRawOffset(),
326                        tzt.getFrom().getDSTSavings());
327                if (firstStart.getTime() == tzt.getTime()) {
328                    // Just add the rule as is
329                    filteredRules.add(ar);
330                } else {
331                    // Calculate the transition year
332                    int[] dfields = new int[6];
333                    Grego.timeToFields(tzt.getTime(), dfields);
334                    // Recreate the rule
335                    AnnualTimeZoneRule newar = new AnnualTimeZoneRule(ar.getName(),
336                            ar.getRawOffset(), ar.getDSTSavings(),
337                            ar.getRule(), dfields[0], ar.getEndYear());
338                    filteredRules.add(newar);
339                }
340                // Check if this is a final rule
341                if (ar.getEndYear() == AnnualTimeZoneRule.MAX_YEAR) {
342                    // After both final standard and dst rule are processed,
343                    // exit this while loop.
344                    if (ar.getDSTSavings() == 0) {
345                        bFinalStd = true;
346                    } else {
347                        bFinalDst = true;
348                    }
349                }
350            }
351            isProcessed.set(ruleIdx);
352        }
353        TimeZoneRule[] rules = filteredRules.toArray(new TimeZoneRule[filteredRules.size()]);
354        return rules;
355    }
356
357    /**
358     * <strong>[icu]</strong> Returns the array of <code>TimeZoneRule</code> which represents the rule of
359     * this time zone object near the specified date.  Some applications are not
360     * capable to handle historic time zone rule changes.  Also some applications
361     * can only handle certain type of rule definitions.  This method returns
362     * either a single <code>InitialTimeZoneRule</code> if this time zone does not
363     * have any daylight saving time within 1 year from the specified time, or a
364     * pair of <code>AnnualTimeZoneRule</code> whose rule type is
365     * <code>DateTimeRule.DOW</code> for date and <code>DateTimeRule.WALL_TIME</code>
366     * for time with a single <code>InitialTimeZoneRule</code> representing the
367     * initial time, when this time zone observes daylight saving time near the
368     * specified date.  Thus, the result may be only valid for dates around the
369     * specified date.
370     *
371     * @param date The date to be used for <code>TimeZoneRule</code> extraction.
372     * @return The array of <code>TimeZoneRule</code>, either a single
373     * <code>InitialTimeZoneRule</code> object, or a pair of <code>AnnualTimeZoneRule</code>
374     * with a single <code>InitialTimeZoneRule</code>.  The first element in the
375     * array is always a <code>InitialTimeZoneRule</code>.
376     */
377    public TimeZoneRule[] getSimpleTimeZoneRulesNear(long date) {
378        AnnualTimeZoneRule[] annualRules = null;
379        TimeZoneRule initialRule = null;
380        // Get the next transition
381        TimeZoneTransition tr = getNextTransition(date, false);
382        if (tr != null) {
383            String initialName = tr.getFrom().getName();
384            int initialRaw = tr.getFrom().getRawOffset();
385            int initialDst = tr.getFrom().getDSTSavings();
386
387            // Check if the next transition is either DST->STD or STD->DST and
388            // within roughly 1 year from the specified date
389            long nextTransitionTime = tr.getTime();
390            if (((tr.getFrom().getDSTSavings() == 0 && tr.getTo().getDSTSavings() != 0)
391                    || (tr.getFrom().getDSTSavings() != 0 && tr.getTo().getDSTSavings() == 0))
392                        && date + MILLIS_PER_YEAR > nextTransitionTime) {
393                annualRules = new AnnualTimeZoneRule[2];
394                // Get local wall time for the transition time
395                int dtfields[] = Grego.timeToFields(nextTransitionTime
396                        + tr.getFrom().getRawOffset() + tr.getFrom().getDSTSavings(), null);
397                int weekInMonth = Grego.getDayOfWeekInMonth(dtfields[0], dtfields[1], dtfields[2]);
398                // Create DOW rule
399                DateTimeRule dtr = new DateTimeRule(dtfields[1], weekInMonth, dtfields[3],
400                        dtfields[5], DateTimeRule.WALL_TIME);
401
402                AnnualTimeZoneRule secondRule = null;
403
404                // Note:  SimpleTimeZone does not support raw offset change.
405                // So we always use raw offset of the given time for the rule,
406                // even raw offset is changed.  This will result that the result
407                // zone to return wrong offset after the transition.
408                // When we encounter such case, we do not inspect next next
409                // transition for another rule.
410                annualRules[0] = new AnnualTimeZoneRule(tr.getTo().getName(),
411                        initialRaw, tr.getTo().getDSTSavings(),
412                        dtr, dtfields[0], AnnualTimeZoneRule.MAX_YEAR);
413
414                if (tr.getTo().getRawOffset() == initialRaw) {
415
416                    // Get the next next transition
417                    tr = getNextTransition(nextTransitionTime, false);
418                    if (tr != null) {
419                        // Check if the next next transition is either DST->STD or STD->DST
420                        // and within roughly 1 year from the next transition
421                        if (((tr.getFrom().getDSTSavings() == 0 && tr.getTo().getDSTSavings() != 0)
422                                || (tr.getFrom().getDSTSavings() != 0
423                                    && tr.getTo().getDSTSavings() == 0))
424                            && nextTransitionTime + MILLIS_PER_YEAR > tr.getTime()) {
425                            // Generate another DOW rule
426                            dtfields = Grego.timeToFields(tr.getTime()
427                                    + tr.getFrom().getRawOffset() + tr.getFrom().getDSTSavings(),
428                                                          dtfields);
429                            weekInMonth = Grego.getDayOfWeekInMonth(dtfields[0], dtfields[1],
430                                                                    dtfields[2]);
431                            dtr = new DateTimeRule(dtfields[1], weekInMonth, dtfields[3],
432                                                   dtfields[5], DateTimeRule.WALL_TIME);
433                            secondRule = new AnnualTimeZoneRule(tr.getTo().getName(),
434                                    tr.getTo().getRawOffset(), tr.getTo().getDSTSavings(),
435                                    dtr, dtfields[0] - 1, AnnualTimeZoneRule.MAX_YEAR);
436                            // Make sure this rule can be applied to the specified date
437                            Date d = secondRule.getPreviousStart(date, tr.getFrom().getRawOffset(),
438                                    tr.getFrom().getDSTSavings(), true);
439                            if (d != null && d.getTime() <= date
440                                    && initialRaw == tr.getTo().getRawOffset()
441                                    && initialDst == tr.getTo().getDSTSavings()) {
442                                // We can use this rule as the second transition rule
443                                annualRules[1] = secondRule;
444                            }
445                        }
446                    }
447                }
448
449                if (annualRules[1] == null) {
450                    // Try previous transition
451                    tr = getPreviousTransition(date, true);
452                    if (tr != null) {
453                        // Check if the previous transition is either DST->STD or STD->DST.
454                        // The actual transition time does not matter here.
455                        if ((tr.getFrom().getDSTSavings() == 0 && tr.getTo().getDSTSavings() != 0)
456                                || (tr.getFrom().getDSTSavings() != 0
457                                    && tr.getTo().getDSTSavings() == 0)) {
458                            // Generate another DOW rule
459                            dtfields = Grego.timeToFields(tr.getTime()
460                                    + tr.getFrom().getRawOffset() + tr.getFrom().getDSTSavings(),
461                                                          dtfields);
462                            weekInMonth = Grego.getDayOfWeekInMonth(dtfields[0], dtfields[1],
463                                                                    dtfields[2]);
464                            dtr = new DateTimeRule(dtfields[1], weekInMonth, dtfields[3],
465                                                   dtfields[5], DateTimeRule.WALL_TIME);
466
467                            // second rule raw/dst offsets should match raw/dst offsets
468                            // at the given time
469                            secondRule = new AnnualTimeZoneRule(
470                                tr.getTo().getName(), initialRaw, initialDst, dtr,
471                                annualRules[0].getStartYear() - 1, AnnualTimeZoneRule.MAX_YEAR);
472
473                            // Check if this rule start after the first rule after the
474                            // specified date
475                            Date d = secondRule.getNextStart(date, tr.getFrom().getRawOffset(),
476                                                             tr.getFrom().getDSTSavings(), false);
477                            if (d.getTime() > nextTransitionTime) {
478                                // We can use this rule as the second transition rule
479                                annualRules[1] = secondRule;
480                            }
481                        }
482                    }
483                }
484                if (annualRules[1] == null) {
485                    // Cannot generate a good pair of AnnualTimeZoneRule
486                    annualRules = null;
487                } else {
488                    // The initial rule should represent the rule before the previous transition
489                    initialName = annualRules[0].getName();
490                    initialRaw = annualRules[0].getRawOffset();
491                    initialDst = annualRules[0].getDSTSavings();
492                }
493            }
494            initialRule = new InitialTimeZoneRule(initialName, initialRaw, initialDst);
495        } else {
496            // Try the previous one
497            tr = getPreviousTransition(date, true);
498            if (tr != null) {
499                initialRule = new InitialTimeZoneRule(tr.getTo().getName(),
500                        tr.getTo().getRawOffset(), tr.getTo().getDSTSavings());
501            } else {
502                // No transitions in the past.  Just use the current offsets
503                int[] offsets = new int[2];
504                getOffset(date, false, offsets);
505                initialRule = new InitialTimeZoneRule(getID(), offsets[0], offsets[1]);
506            }
507        }
508
509        TimeZoneRule[] result = null;
510        if (annualRules == null) {
511            result = new TimeZoneRule[1];
512            result[0] = initialRule;
513        } else {
514            result = new TimeZoneRule[3];
515            result[0] = initialRule;
516            result[1] = annualRules[0];
517            result[2] = annualRules[1];
518        }
519
520        return result;
521    }
522
523    /**
524     * <strong>[icu]</strong> The time type option for standard time used by
525     * {@link #getOffsetFromLocal(long, int, int, int[])}
526     * @deprecated This API is ICU internal only.
527     * @hide draft / provisional / internal are hidden on Android
528     */
529    @Deprecated
530    public static final int LOCAL_STD = 0x01;
531
532    /**
533     * <strong>[icu]</strong> The time type option for daylight saving time used by
534     * {@link #getOffsetFromLocal(long, int, int, int[])}
535     * @deprecated This API is ICU internal only.
536     * @hide draft / provisional / internal are hidden on Android
537     */
538    @Deprecated
539    public static final int LOCAL_DST = 0x03;
540
541    /**
542     * <strong>[icu]</strong> The option designate former time to be used by
543     * {@link #getOffsetFromLocal(long, int, int, int[])}
544     * @deprecated This API is ICU internal only.
545     * @hide draft / provisional / internal are hidden on Android
546     */
547    @Deprecated
548    public static final int LOCAL_FORMER = 0x04;
549
550    /**
551     * <strong>[icu]</strong> The option designate latter time to be used by
552     * {@link #getOffsetFromLocal(long, int, int, int[])}
553     * @deprecated This API is ICU internal only.
554     * @hide draft / provisional / internal are hidden on Android
555     */
556    @Deprecated
557    public static final int LOCAL_LATTER = 0x0C;
558
559    /**
560     * <strong>[icu]</strong> The bit mask for the time type option used by
561     * {@link #getOffsetFromLocal(long, int, int, int[])}
562     * @deprecated This API is ICU internal only.
563     * @hide draft / provisional / internal are hidden on Android
564     */
565    @Deprecated
566    protected static final int STD_DST_MASK = 0x03;
567
568    /**
569     * <strong>[icu]</strong> The bit mask for the former/latter option used by
570     * {@link #getOffsetFromLocal(long, int, int, int[])}
571     * @deprecated This API is ICU internal only.
572     * @hide draft / provisional / internal are hidden on Android
573     */
574    @Deprecated
575    protected static final int FORMER_LATTER_MASK = 0x0C;
576
577    /**
578     * <strong>[icu]</strong> Returns time zone offsets from local wall time.
579     * @deprecated This API is ICU internal only.
580     * @hide draft / provisional / internal are hidden on Android
581     */
582    @Deprecated
583    public void getOffsetFromLocal(long date,
584            int nonExistingTimeOpt, int duplicatedTimeOpt, int[] offsets) {
585        throw new IllegalStateException("Not implemented");
586    }
587
588    /**
589     * Protected no arg constructor.
590     */
591    protected BasicTimeZone() {
592    }
593
594    /**
595     * Constructing a BasicTimeZone with the given time zone ID.
596     * @param ID the time zone ID.
597     * @deprecated This API is ICU internal only.
598     * @hide draft / provisional / internal are hidden on Android
599     */
600    @Deprecated
601    protected BasicTimeZone(String ID) {
602        super(ID);
603    }
604}
605