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