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