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