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