1/* GENERATED SOURCE. DO NOT MODIFY. */ 2// © 2016 and later: Unicode, Inc. and others. 3// License & terms of use: http://www.unicode.org/copyright.html#License 4/* 5 ******************************************************************************* 6 * Copyright (C) 2007-2014, International Business Machines Corporation and * 7 * others. All Rights Reserved. * 8 ******************************************************************************* 9 */ 10package android.icu.util; 11 12import java.util.BitSet; 13import java.util.Date; 14import java.util.LinkedList; 15import java.util.List; 16 17import 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 */ 31public 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 */ 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 */ 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 */ 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 transtion 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 */ 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 */ 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 */ 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<TimeZoneRule>(); 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 */ 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> The time type option for standard time used by 527 * {@link #getOffsetFromLocal(long, int, int, int[])} 528 * @deprecated This API is ICU internal only. 529 * @hide draft / provisional / internal are hidden on Android 530 */ 531 @Deprecated 532 public static final int LOCAL_STD = 0x01; 533 534 /** 535 * <strong>[icu]</strong> The time type option for daylight saving time used by 536 * {@link #getOffsetFromLocal(long, int, int, int[])} 537 * @deprecated This API is ICU internal only. 538 * @hide draft / provisional / internal are hidden on Android 539 */ 540 @Deprecated 541 public static final int LOCAL_DST = 0x03; 542 543 /** 544 * <strong>[icu]</strong> The option designate former time to be used by 545 * {@link #getOffsetFromLocal(long, int, int, int[])} 546 * @deprecated This API is ICU internal only. 547 * @hide draft / provisional / internal are hidden on Android 548 */ 549 @Deprecated 550 public static final int LOCAL_FORMER = 0x04; 551 552 /** 553 * <strong>[icu]</strong> The option designate latter time to be used by 554 * {@link #getOffsetFromLocal(long, int, int, int[])} 555 * @deprecated This API is ICU internal only. 556 * @hide draft / provisional / internal are hidden on Android 557 */ 558 @Deprecated 559 public static final int LOCAL_LATTER = 0x0C; 560 561 /** 562 * <strong>[icu]</strong> The bit mask for the time type option used by 563 * {@link #getOffsetFromLocal(long, int, int, int[])} 564 * @deprecated This API is ICU internal only. 565 * @hide draft / provisional / internal are hidden on Android 566 */ 567 @Deprecated 568 protected static final int STD_DST_MASK = 0x03; 569 570 /** 571 * <strong>[icu]</strong> The bit mask for the former/latter option used by 572 * {@link #getOffsetFromLocal(long, int, int, int[])} 573 * @deprecated This API is ICU internal only. 574 * @hide draft / provisional / internal are hidden on Android 575 */ 576 @Deprecated 577 protected static final int FORMER_LATTER_MASK = 0x0C; 578 579 /** 580 * <strong>[icu]</strong> Returns time zone offsets from local wall time. 581 * @deprecated This API is ICU internal only. 582 * @hide draft / provisional / internal are hidden on Android 583 */ 584 @Deprecated 585 public void getOffsetFromLocal(long date, 586 int nonExistingTimeOpt, int duplicatedTimeOpt, int[] offsets) { 587 throw new IllegalStateException("Not implemented"); 588 } 589 590 /** 591 * Protected no arg constructor. 592 */ 593 protected BasicTimeZone() { 594 } 595 596 /** 597 * Constructing a BasicTimeZone with the given time zone ID. 598 * @param ID the time zone ID. 599 * @deprecated This API is ICU internal only. 600 * @hide draft / provisional / internal are hidden on Android 601 */ 602 @Deprecated 603 protected BasicTimeZone(String ID) { 604 super(ID); 605 } 606} 607