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 * Copyright (C) 1996-2016, International Business Machines 6 * Corporation and others. All Rights Reserved. 7 */ 8 9 package ohos.global.icu.util; 10 11 import java.io.IOException; 12 import java.util.Date; 13 14 import ohos.global.icu.impl.Grego; 15 16 /** 17 * <strong>[icu enhancement]</strong> ICU's replacement for {@link java.util.SimpleTimeZone}. Methods, fields, and other functionality specific to ICU are labeled '<strong>[icu]</strong>'. 18 * 19 * <p><code>SimpleTimeZone</code> is a concrete subclass of <code>TimeZone</code> 20 * that represents a time zone for use with a Gregorian calendar. This 21 * class does not handle historical changes. 22 * 23 * <p>Use a negative value for <code>dayOfWeekInMonth</code> to indicate that 24 * <code>SimpleTimeZone</code> should count from the end of the month backwards. For 25 * example, if Daylight Savings Time starts or ends at the last Sunday in a month, use 26 * <code>dayOfWeekInMonth = -1</code> along with <code>dayOfWeek = Calendar.SUNDAY</code> 27 * to specify the rule. 28 * 29 * @see Calendar 30 * @see GregorianCalendar 31 * @see TimeZone 32 * @author Deborah Goldsmith, Mark Davis, Chen-Lieh Huang, Alan Liu 33 * @hide exposed on OHOS 34 */ 35 public class SimpleTimeZone extends BasicTimeZone { 36 private static final long serialVersionUID = -7034676239311322769L; 37 38 /** 39 * Constant for a mode of start or end time specified as local wall time. 40 */ 41 public static final int WALL_TIME = 0; 42 43 /** 44 * Constant for a mode of start or end time specified as local standard time. 45 */ 46 public static final int STANDARD_TIME = 1; 47 48 /** 49 * Constant for a mode of start or end time specified as UTC. 50 */ 51 public static final int UTC_TIME = 2; 52 53 /** 54 * Constructs a SimpleTimeZone with the given base time zone offset from GMT 55 * and time zone ID. Timezone IDs can be obtained from 56 * TimeZone.getAvailableIDs. Normally you should use TimeZone.getDefault to 57 * construct a TimeZone. 58 * 59 * @param rawOffset The given base time zone offset to GMT. 60 * @param ID The time zone ID which is obtained from 61 * TimeZone.getAvailableIDs. 62 */ SimpleTimeZone(int rawOffset, String ID)63 public SimpleTimeZone(int rawOffset, String ID) { 64 super(ID); 65 construct(rawOffset, 0, 0, 0, 66 0, WALL_TIME, 67 0, 0, 0, 68 0, WALL_TIME, 69 Grego.MILLIS_PER_HOUR); 70 } 71 72 /** 73 * Constructs a SimpleTimeZone with the given base time zone offset from 74 * GMT, time zone ID, time to start and end the daylight time. Timezone IDs 75 * can be obtained from TimeZone.getAvailableIDs. Normally you should use 76 * TimeZone.getDefault to create a TimeZone. For a time zone that does not 77 * use daylight saving time, do not use this constructor; instead you should 78 * use SimpleTimeZone(rawOffset, ID). 79 * 80 * By default, this constructor specifies day-of-week-in-month rules. That 81 * is, if the startDay is 1, and the startDayOfWeek is SUNDAY, then this 82 * indicates the first Sunday in the startMonth. A startDay of -1 likewise 83 * indicates the last Sunday. However, by using negative or zero values for 84 * certain parameters, other types of rules can be specified. 85 * 86 * Day of month. To specify an exact day of the month, such as March 1, set 87 * startDayOfWeek to zero. 88 * 89 * Day of week after day of month. To specify the first day of the week 90 * occurring on or after an exact day of the month, make the day of the week 91 * negative. For example, if startDay is 5 and startDayOfWeek is -MONDAY, 92 * this indicates the first Monday on or after the 5th day of the 93 * startMonth. 94 * 95 * Day of week before day of month. To specify the last day of the week 96 * occurring on or before an exact day of the month, make the day of the 97 * week and the day of the month negative. For example, if startDay is -21 98 * and startDayOfWeek is -WEDNESDAY, this indicates the last Wednesday on or 99 * before the 21st of the startMonth. 100 * 101 * The above examples refer to the startMonth, startDay, and startDayOfWeek; 102 * the same applies for the endMonth, endDay, and endDayOfWeek. 103 * 104 * @param rawOffset The given base time zone offset to GMT. 105 * @param ID The time zone ID which is obtained from 106 * TimeZone.getAvailableIDs. 107 * @param startMonth The daylight savings starting month. Month is 108 * 0-based. eg, 0 for January. 109 * @param startDay The daylight savings starting 110 * day-of-week-in-month. Please see the member 111 * description for an example. 112 * @param startDayOfWeek The daylight savings starting day-of-week. Please 113 * see the member description for an example. 114 * @param startTime The daylight savings starting time in local wall 115 * time, which is standard time in this case. Please see the 116 * member description for an example. 117 * @param endMonth The daylight savings ending month. Month is 118 * 0-based. eg, 0 for January. 119 * @param endDay The daylight savings ending day-of-week-in-month. 120 * Please see the member description for an example. 121 * @param endDayOfWeek The daylight savings ending day-of-week. Please 122 * see the member description for an example. 123 * @param endTime The daylight savings ending time in local wall time, 124 * which is daylight time in this case. Please see the 125 * member description for an example. 126 * @throws IllegalArgumentException the month, day, dayOfWeek, or time 127 * parameters are out of range for the start or end rule 128 */ SimpleTimeZone(int rawOffset, String ID, int startMonth, int startDay, int startDayOfWeek, int startTime, int endMonth, int endDay, int endDayOfWeek, int endTime)129 public SimpleTimeZone(int rawOffset, String ID, 130 int startMonth, int startDay, int startDayOfWeek, int startTime, 131 int endMonth, int endDay, int endDayOfWeek, int endTime) { 132 super(ID); 133 construct(rawOffset, 134 startMonth, startDay, startDayOfWeek, 135 startTime, WALL_TIME, 136 endMonth, endDay, endDayOfWeek, 137 endTime, WALL_TIME, 138 Grego.MILLIS_PER_HOUR); 139 } 140 141 /** 142 * Constructs a SimpleTimeZone with the given base time zone offset from 143 * GMT, time zone ID, time and its mode to start and end the daylight time. 144 * The mode specifies either {@link #WALL_TIME} or {@link #STANDARD_TIME} 145 * or {@link #UTC_TIME}. 146 * 147 * @param rawOffset The given base time zone offset to GMT. 148 * @param ID The time zone ID which is obtained from 149 * TimeZone.getAvailableIDs. 150 * @param startMonth The daylight savings starting month. Month is 151 * 0-based. eg, 0 for January. 152 * @param startDay The daylight savings starting 153 * day-of-week-in-month. Please see the member 154 * description for an example. 155 * @param startDayOfWeek The daylight savings starting day-of-week. Please 156 * see the member description for an example. 157 * @param startTime The daylight savings starting time in local wall 158 * time, which is standard time in this case. Please see the 159 * member description for an example. 160 * @param startTimeMode The mode of the start time specified by startTime. 161 * @param endMonth The daylight savings ending month. Month is 162 * 0-based. eg, 0 for January. 163 * @param endDay The daylight savings ending day-of-week-in-month. 164 * Please see the member description for an example. 165 * @param endDayOfWeek The daylight savings ending day-of-week. Please 166 * see the member description for an example. 167 * @param endTime The daylight savings ending time in local wall time, 168 * which is daylight time in this case. Please see the 169 * member description for an example. 170 * @param endTimeMode The mode of the end time specified by endTime. 171 * @param dstSavings The amount of time in ms saved during DST. 172 * @throws IllegalArgumentException the month, day, dayOfWeek, or time 173 * parameters are out of range for the start or end rule 174 */ SimpleTimeZone(int rawOffset, String ID, int startMonth, int startDay, int startDayOfWeek, int startTime, int startTimeMode, int endMonth, int endDay, int endDayOfWeek, int endTime, int endTimeMode,int dstSavings)175 public SimpleTimeZone(int rawOffset, String ID, 176 int startMonth, int startDay, 177 int startDayOfWeek, int startTime, 178 int startTimeMode, 179 int endMonth, int endDay, 180 int endDayOfWeek, int endTime, 181 int endTimeMode,int dstSavings){ 182 super(ID); 183 construct(rawOffset, 184 startMonth, startDay, startDayOfWeek, 185 startTime, startTimeMode, 186 endMonth, endDay, endDayOfWeek, 187 endTime, endTimeMode, 188 dstSavings); 189 } 190 191 /** 192 * Constructor. This constructor is identical to the 10-argument 193 * constructor, but also takes a dstSavings parameter. 194 * @param rawOffset The given base time zone offset to GMT. 195 * @param ID The time zone ID which is obtained from 196 * TimeZone.getAvailableIDs. 197 * @param startMonth The daylight savings starting month. Month is 198 * 0-based. eg, 0 for January. 199 * @param startDay The daylight savings starting 200 * day-of-week-in-month. Please see the member 201 * description for an example. 202 * @param startDayOfWeek The daylight savings starting day-of-week. Please 203 * see the member description for an example. 204 * @param startTime The daylight savings starting time in local wall 205 * time, which is standard time in this case. Please see the 206 * member description for an example. 207 * @param endMonth The daylight savings ending month. Month is 208 * 0-based. eg, 0 for January. 209 * @param endDay The daylight savings ending day-of-week-in-month. 210 * Please see the member description for an example. 211 * @param endDayOfWeek The daylight savings ending day-of-week. Please 212 * see the member description for an example. 213 * @param endTime The daylight savings ending time in local wall time, 214 * which is daylight time in this case. Please see the 215 * member description for an example. 216 * @param dstSavings The amount of time in ms saved during DST. 217 * @throws IllegalArgumentException the month, day, dayOfWeek, or time 218 * parameters are out of range for the start or end rule 219 */ SimpleTimeZone(int rawOffset, String ID, int startMonth, int startDay, int startDayOfWeek, int startTime, int endMonth, int endDay, int endDayOfWeek, int endTime, int dstSavings)220 public SimpleTimeZone(int rawOffset, String ID, 221 int startMonth, int startDay, int startDayOfWeek, int startTime, 222 int endMonth, int endDay, int endDayOfWeek, int endTime, 223 int dstSavings) { 224 super(ID); 225 construct(rawOffset, 226 startMonth, startDay, startDayOfWeek, 227 startTime, WALL_TIME, 228 endMonth, endDay, endDayOfWeek, 229 endTime, WALL_TIME, 230 dstSavings); 231 } 232 233 /** 234 * {@inheritDoc} 235 */ 236 @Override setID(String ID)237 public void setID(String ID) { 238 if (isFrozen()) { 239 throw new UnsupportedOperationException("Attempt to modify a frozen SimpleTimeZone instance."); 240 } 241 super.setID(ID); 242 transitionRulesInitialized = false; 243 } 244 245 /** 246 * Overrides TimeZone 247 * Sets the base time zone offset to GMT. 248 * This is the offset to add "to" UTC to get local time. 249 * @param offsetMillis the raw offset of the time zone 250 */ 251 @Override setRawOffset(int offsetMillis)252 public void setRawOffset(int offsetMillis) { 253 if (isFrozen()) { 254 throw new UnsupportedOperationException("Attempt to modify a frozen SimpleTimeZone instance."); 255 } 256 257 raw = offsetMillis; 258 transitionRulesInitialized = false; 259 } 260 261 /** 262 * Overrides TimeZone 263 * Gets the GMT offset for this time zone. 264 * @return the raw offset 265 */ 266 @Override getRawOffset()267 public int getRawOffset() { 268 return raw; 269 } 270 271 /** 272 * Sets the daylight savings starting year. 273 * 274 * @param year The daylight savings starting year. 275 */ setStartYear(int year)276 public void setStartYear(int year) { 277 if (isFrozen()) { 278 throw new UnsupportedOperationException("Attempt to modify a frozen SimpleTimeZone instance."); 279 } 280 281 getSTZInfo().sy = year; 282 this.startYear = year; 283 transitionRulesInitialized = false; 284 } 285 286 /** 287 * Sets the daylight savings starting rule. For example, Daylight Savings 288 * Time starts at the second Sunday in March, at 2 AM in standard time. 289 * Therefore, you can set the start rule by calling: 290 * setStartRule(Calendar.MARCH, 2, Calendar.SUNDAY, 2*60*60*1000); 291 * 292 * @param month The daylight savings starting month. Month is 293 * 0-based. eg, 0 for January. 294 * @param dayOfWeekInMonth The daylight savings starting 295 * day-of-week-in-month. Please see the member 296 * description for an example. 297 * @param dayOfWeek The daylight savings starting day-of-week. 298 * Please see the member description for an 299 * example. 300 * @param time The daylight savings starting time in local wall 301 * time, which is standard time in this case. Please see 302 * the member description for an example. 303 * @throws IllegalArgumentException the month, dayOfWeekInMonth, 304 * dayOfWeek, or time parameters are out of range 305 */ setStartRule(int month, int dayOfWeekInMonth, int dayOfWeek, int time)306 public void setStartRule(int month, int dayOfWeekInMonth, int dayOfWeek, 307 int time) { 308 if (isFrozen()) { 309 throw new UnsupportedOperationException("Attempt to modify a frozen SimpleTimeZone instance."); 310 } 311 312 getSTZInfo().setStart(month, dayOfWeekInMonth, dayOfWeek, time, -1, false); 313 setStartRule(month, dayOfWeekInMonth, dayOfWeek, time, WALL_TIME); 314 } 315 316 /** 317 * Sets the daylight savings starting rule. For example, in the U.S., Daylight Savings 318 * Time starts at the second Sunday in March, at 2 AM in standard time. 319 * Therefore, you can set the start rule by calling: 320 * <code>setStartRule(Calendar.MARCH, 2, Calendar.SUNDAY, 2*60*60*1000);</code> 321 * The dayOfWeekInMonth and dayOfWeek parameters together specify how to calculate 322 * the exact starting date. Their exact meaning depend on their respective signs, 323 * allowing various types of rules to be constructed, as follows:<ul> 324 * <li>If both dayOfWeekInMonth and dayOfWeek are positive, they specify the 325 * day of week in the month (e.g., (2, WEDNESDAY) is the second Wednesday 326 * of the month). 327 * <li>If dayOfWeek is positive and dayOfWeekInMonth is negative, they specify 328 * the day of week in the month counting backward from the end of the month. 329 * (e.g., (-1, MONDAY) is the last Monday in the month) 330 * <li>If dayOfWeek is zero and dayOfWeekInMonth is positive, dayOfWeekInMonth 331 * specifies the day of the month, regardless of what day of the week it is. 332 * (e.g., (10, 0) is the tenth day of the month) 333 * <li>If dayOfWeek is zero and dayOfWeekInMonth is negative, dayOfWeekInMonth 334 * specifies the day of the month counting backward from the end of the 335 * month, regardless of what day of the week it is (e.g., (-2, 0) is the 336 * next-to-last day of the month). 337 * <li>If dayOfWeek is negative and dayOfWeekInMonth is positive, they specify the 338 * first specified day of the week on or after the specfied day of the month. 339 * (e.g., (15, -SUNDAY) is the first Sunday after the 15th of the month 340 * [or the 15th itself if the 15th is a Sunday].) 341 * <li>If dayOfWeek and DayOfWeekInMonth are both negative, they specify the 342 * last specified day of the week on or before the specified day of the month. 343 * (e.g., (-20, -TUESDAY) is the last Tuesday before the 20th of the month 344 * [or the 20th itself if the 20th is a Tuesday].)</ul> 345 * @param month the daylight savings starting month. Month is 0-based. 346 * eg, 0 for January. 347 * @param dayOfWeekInMonth the daylight savings starting 348 * day-of-week-in-month. Please see the member description for an example. 349 * @param dayOfWeek the daylight savings starting day-of-week. Please see 350 * the member description for an example. 351 * @param time the daylight savings starting time. Please see the member 352 * description for an example. 353 */ setStartRule(int month, int dayOfWeekInMonth, int dayOfWeek, int time, int mode)354 private void setStartRule(int month, int dayOfWeekInMonth, int dayOfWeek, int time, int mode) { 355 assert (!isFrozen()); 356 357 startMonth = month; 358 startDay = dayOfWeekInMonth; 359 startDayOfWeek = dayOfWeek; 360 startTime = time; 361 startTimeMode = mode; 362 decodeStartRule(); 363 364 transitionRulesInitialized = false; 365 } 366 367 /** 368 * Sets the DST start rule to a fixed date within a month. 369 * 370 * @param month The month in which this rule occurs (0-based). 371 * @param dayOfMonth The date in that month (1-based). 372 * @param time The time of that day (number of millis after midnight) 373 * when DST takes effect in local wall time, which is 374 * standard time in this case. 375 * @throws IllegalArgumentException the month, 376 * dayOfMonth, or time parameters are out of range 377 */ setStartRule(int month, int dayOfMonth, int time)378 public void setStartRule(int month, int dayOfMonth, int time) { 379 if (isFrozen()) { 380 throw new UnsupportedOperationException("Attempt to modify a frozen SimpleTimeZone instance."); 381 } 382 383 getSTZInfo().setStart(month, -1, -1, time, dayOfMonth, false); 384 setStartRule(month, dayOfMonth, 0, time, WALL_TIME); 385 } 386 387 /** 388 * Sets the DST start rule to a weekday before or after a give date within 389 * a month, e.g., the first Monday on or after the 8th. 390 * 391 * @param month The month in which this rule occurs (0-based). 392 * @param dayOfMonth A date within that month (1-based). 393 * @param dayOfWeek The day of the week on which this rule occurs. 394 * @param time The time of that day (number of millis after midnight) 395 * when DST takes effect in local wall time, which is 396 * standard time in this case. 397 * @param after If true, this rule selects the first dayOfWeek on 398 * or after dayOfMonth. If false, this rule selects 399 * the last dayOfWeek on or before dayOfMonth. 400 * @throws IllegalArgumentException the month, dayOfMonth, 401 * dayOfWeek, or time parameters are out of range 402 */ setStartRule(int month, int dayOfMonth, int dayOfWeek, int time, boolean after)403 public void setStartRule(int month, int dayOfMonth, int dayOfWeek, int time, boolean after) { 404 if (isFrozen()) { 405 throw new UnsupportedOperationException("Attempt to modify a frozen SimpleTimeZone instance."); 406 } 407 408 getSTZInfo().setStart(month, -1, dayOfWeek, time, dayOfMonth, after); 409 setStartRule(month, after ? dayOfMonth : -dayOfMonth, 410 -dayOfWeek, time, WALL_TIME); 411 } 412 413 /** 414 * Sets the daylight savings ending rule. For example, if Daylight Savings Time 415 * ends at the last (-1) Sunday in October, at 2 AM in standard time, 416 * you can set the end rule by calling: 417 * <code>setEndRule(Calendar.OCTOBER, -1, Calendar.SUNDAY, 2*60*60*1000);</code> 418 * 419 * @param month The daylight savings ending month. Month is 420 * 0-based. eg, 0 for January. 421 * @param dayOfWeekInMonth The daylight savings ending 422 * day-of-week-in-month. Please see the member 423 * description for an example. 424 * @param dayOfWeek The daylight savings ending day-of-week. Please 425 * see the member description for an example. 426 * @param time The daylight savings ending time in local wall time, 427 * which is daylight time in this case. Please see the 428 * member description for an example. 429 * @throws IllegalArgumentException the month, dayOfWeekInMonth, 430 * dayOfWeek, or time parameters are out of range 431 */ setEndRule(int month, int dayOfWeekInMonth, int dayOfWeek, int time)432 public void setEndRule(int month, int dayOfWeekInMonth, int dayOfWeek, int time) { 433 if (isFrozen()) { 434 throw new UnsupportedOperationException("Attempt to modify a frozen SimpleTimeZone instance."); 435 } 436 437 getSTZInfo().setEnd(month, dayOfWeekInMonth, dayOfWeek, time, -1, false); 438 setEndRule(month, dayOfWeekInMonth, dayOfWeek, time, WALL_TIME); 439 } 440 441 /** 442 * Sets the DST end rule to a fixed date within a month. 443 * 444 * @param month The month in which this rule occurs (0-based). 445 * @param dayOfMonth The date in that month (1-based). 446 * @param time The time of that day (number of millis after midnight) 447 * when DST ends in local wall time, which is daylight 448 * time in this case. 449 * @throws IllegalArgumentException the month, 450 * dayOfMonth, or time parameters are out of range 451 */ setEndRule(int month, int dayOfMonth, int time)452 public void setEndRule(int month, int dayOfMonth, int time) { 453 if (isFrozen()) { 454 throw new UnsupportedOperationException("Attempt to modify a frozen SimpleTimeZone instance."); 455 } 456 457 getSTZInfo().setEnd(month, -1, -1, time, dayOfMonth, false); 458 setEndRule(month, dayOfMonth, WALL_TIME, time); 459 } 460 461 /** 462 * Sets the DST end rule to a weekday before or after a give date within 463 * a month, e.g., the first Monday on or after the 8th. 464 * 465 * @param month The month in which this rule occurs (0-based). 466 * @param dayOfMonth A date within that month (1-based). 467 * @param dayOfWeek The day of the week on which this rule occurs. 468 * @param time The time of that day (number of millis after midnight) 469 * when DST ends in local wall time, which is daylight 470 * time in this case. 471 * @param after If true, this rule selects the first dayOfWeek on 472 * or after dayOfMonth. If false, this rule selects 473 * the last dayOfWeek on or before dayOfMonth. 474 * @throws IllegalArgumentException the month, dayOfMonth, 475 * dayOfWeek, or time parameters are out of range 476 */ setEndRule(int month, int dayOfMonth, int dayOfWeek, int time, boolean after)477 public void setEndRule(int month, int dayOfMonth, int dayOfWeek, int time, boolean after) { 478 if (isFrozen()) { 479 throw new UnsupportedOperationException("Attempt to modify a frozen SimpleTimeZone instance."); 480 } 481 482 getSTZInfo().setEnd(month, -1, dayOfWeek, time, dayOfMonth, after); 483 setEndRule(month, dayOfMonth, dayOfWeek, time, WALL_TIME, after); 484 } 485 setEndRule(int month, int dayOfMonth, int dayOfWeek, int time, int mode, boolean after)486 private void setEndRule(int month, int dayOfMonth, int dayOfWeek, 487 int time, int mode, boolean after){ 488 assert (!isFrozen()); 489 setEndRule(month, after ? dayOfMonth : -dayOfMonth, -dayOfWeek, time, mode); 490 } 491 492 /** 493 * Sets the daylight savings ending rule. For example, in the U.S., Daylight 494 * Savings Time ends at the first Sunday in November, at 2 AM in standard time. 495 * Therefore, you can set the end rule by calling: 496 * setEndRule(Calendar.NOVEMBER, 1, Calendar.SUNDAY, 2*60*60*1000); 497 * Various other types of rules can be specified by manipulating the dayOfWeek 498 * and dayOfWeekInMonth parameters. For complete details, see the documentation 499 * for setStartRule(). 500 * @param month the daylight savings ending month. Month is 0-based. 501 * eg, 0 for January. 502 * @param dayOfWeekInMonth the daylight savings ending 503 * day-of-week-in-month. See setStartRule() for a complete explanation. 504 * @param dayOfWeek the daylight savings ending day-of-week. See setStartRule() 505 * for a complete explanation. 506 * @param time the daylight savings ending time. Please see the member 507 * description for an example. 508 */ setEndRule(int month, int dayOfWeekInMonth, int dayOfWeek, int time, int mode)509 private void setEndRule(int month, int dayOfWeekInMonth, int dayOfWeek, int time, int mode){ 510 assert (!isFrozen()); 511 512 endMonth = month; 513 endDay = dayOfWeekInMonth; 514 endDayOfWeek = dayOfWeek; 515 endTime = time; 516 endTimeMode = mode; 517 decodeEndRule(); 518 519 transitionRulesInitialized = false; 520 } 521 522 /** 523 * Sets the amount of time in ms that the clock is advanced during DST. 524 * @param millisSavedDuringDST the number of milliseconds the time is 525 * advanced with respect to standard time when the daylight savings rules 526 * are in effect. Typically one hour (+3600000). The amount could be negative, 527 * but not 0. 528 */ setDSTSavings(int millisSavedDuringDST)529 public void setDSTSavings(int millisSavedDuringDST) { 530 if (isFrozen()) { 531 throw new UnsupportedOperationException("Attempt to modify a frozen SimpleTimeZone instance."); 532 } 533 534 if (millisSavedDuringDST == 0) { 535 throw new IllegalArgumentException(); 536 } 537 dst = millisSavedDuringDST; 538 539 transitionRulesInitialized = false; 540 } 541 542 /** 543 * Returns the amount of time in ms that the clock is advanced during DST. 544 * @return the number of milliseconds the time is 545 * advanced with respect to standard time when the daylight savings rules 546 * are in effect. Typically one hour (3600000). The amount could be negative, 547 * but not 0. 548 */ 549 @Override getDSTSavings()550 public int getDSTSavings() { 551 return dst; 552 } 553 554 /** 555 * Returns the java.util.SimpleTimeZone that this class wraps. 556 * 557 java.util.SimpleTimeZone unwrapSTZ() { 558 return (java.util.SimpleTimeZone) unwrap(); 559 } 560 */ 561 562 // on JDK 1.4 and later, can't deserialize a SimpleTimeZone as a SimpleTimeZone... readObject(java.io.ObjectInputStream in)563 private void readObject(java.io.ObjectInputStream in) throws IOException, 564 ClassNotFoundException { 565 in.defaultReadObject(); 566 /* 567 String id = getID(); 568 if (id!=null && !(zone instanceof java.util.SimpleTimeZone && zone.getID().equals(id))) { 569 // System.out.println("*** readjust " + zone.getClass().getName() + 570 // " " + zone.getID() + " ***"); 571 java.util.SimpleTimeZone stz = 572 new java.util.SimpleTimeZone(raw, id); 573 if (dst != 0) { 574 stz.setDSTSavings(dst); 575 // if it is 0, then there shouldn't be start/end rules and the default 576 // behavior should be no dst 577 } 578 579 if (xinfo != null) { 580 xinfo.applyTo(stz); 581 } 582 zoneJDK = stz; 583 } 584 */ 585 /* set all instance variables in this object 586 * to the values in zone 587 */ 588 if (xinfo != null) { 589 xinfo.applyTo(this); 590 } 591 } 592 593 /** 594 * Returns a string representation of this object. 595 * @return a string representation of this object 596 */ 597 @Override toString()598 public String toString() { 599 return "SimpleTimeZone: " + getID(); 600 } 601 getSTZInfo()602 private STZInfo getSTZInfo() { 603 if (xinfo == null) { 604 xinfo = new STZInfo(); 605 } 606 return xinfo; 607 } 608 609 // Use only for decodeStartRule() and decodeEndRule() where the year is not 610 // available. Set February to 29 days to accomodate rules with that date 611 // and day-of-week-on-or-before-that-date mode (DOW_LE_DOM_MODE). 612 // The compareToRule() method adjusts to February 28 in non-leap years. 613 // 614 // For actual getOffset() calculations, use TimeZone::monthLength() and 615 // TimeZone::previousMonthLength() which take leap years into account. 616 // We handle leap years assuming always 617 // Gregorian, since we know they didn't have daylight time when 618 // Gregorian calendar started. 619 private final static byte staticMonthLength[] = {31,29,31,30,31,30,31,31,30,31,30,31}; 620 621 /** 622 * {@inheritDoc} 623 */ 624 @Override getOffset(int era, int year, int month, int day, int dayOfWeek, int millis)625 public int getOffset(int era, int year, int month, int day, 626 int dayOfWeek, int millis) 627 { 628 // Check the month before calling Grego.monthLength(). This 629 // duplicates the test that occurs in the 7-argument getOffset(), 630 // however, this is unavoidable. We don't mind because this method, in 631 // fact, should not be called; internal code should always call the 632 // 7-argument getOffset(), and outside code should use Calendar.get(int 633 // field) with fields ZONE_OFFSET and DST_OFFSET. We can't get rid of 634 // this method because it's public API. - liu 8/10/98 635 if(month < Calendar.JANUARY || month > Calendar.DECEMBER) { 636 throw new IllegalArgumentException(); 637 } 638 639 return getOffset(era, year, month, day, dayOfWeek, millis, Grego.monthLength(year, month)); 640 } 641 642 /** 643 * @deprecated This API is ICU internal only. 644 * @hide draft / provisional / internal are hidden on OHOS 645 */ 646 @Deprecated getOffset(int era, int year, int month, int day, int dayOfWeek, int millis, int monthLength)647 public int getOffset(int era, int year, int month, int day, 648 int dayOfWeek, int millis, 649 int monthLength) { 650 // Check the month before calling Grego.monthLength(). This 651 // duplicates a test that occurs in the 9-argument getOffset(), 652 // however, this is unavoidable. We don't mind because this method, in 653 // fact, should not be called; internal code should always call the 654 // 9-argument getOffset(), and outside code should use Calendar.get(int 655 // field) with fields ZONE_OFFSET and DST_OFFSET. We can't get rid of 656 // this method because it's public API. - liu 8/10/98 657 if(month < Calendar.JANUARY || month > Calendar.DECEMBER) { 658 throw new IllegalArgumentException(); 659 } 660 661 return getOffset(era, year, month, day, dayOfWeek, millis, 662 Grego.monthLength(year, month), Grego.previousMonthLength(year, month)); 663 } 664 getOffset(int era, int year, int month, int day, int dayOfWeek, int millis, int monthLength, int prevMonthLength )665 private int getOffset(int era, int year, int month, int day, 666 int dayOfWeek, int millis, 667 int monthLength, int prevMonthLength ){ 668 669 if (true) { 670 /* Use this parameter checking code for normal operation. Only one 671 * of these two blocks should actually get compiled into the class 672 * file. */ 673 if ((era != GregorianCalendar.AD && era != GregorianCalendar.BC) 674 || month < Calendar.JANUARY 675 || month > Calendar.DECEMBER 676 || day < 1 677 || day > monthLength 678 || dayOfWeek < Calendar.SUNDAY 679 || dayOfWeek > Calendar.SATURDAY 680 || millis < 0 681 || millis >= Grego.MILLIS_PER_DAY 682 || monthLength < 28 683 || monthLength > 31 684 || prevMonthLength < 28 685 || prevMonthLength > 31) { 686 throw new IllegalArgumentException(); 687 } 688 } 689 //Eclipse stated the following is "dead code" 690 /*else { 691 // This parameter checking code is better for debugging, but 692 // overkill for normal operation. Only one of these two blocks 693 // should actually get compiled into the class file. 694 if (era != GregorianCalendar.AD && era != GregorianCalendar.BC) { 695 throw new IllegalArgumentException("Illegal era " + era); 696 } 697 if (month < Calendar.JANUARY 698 || month > Calendar.DECEMBER) { 699 throw new IllegalArgumentException("Illegal month " + month); 700 } 701 if (day < 1 702 || day > monthLength) { 703 throw new IllegalArgumentException("Illegal day " + day+" max month len: "+monthLength); 704 } 705 if (dayOfWeek < Calendar.SUNDAY 706 || dayOfWeek > Calendar.SATURDAY) { 707 throw new IllegalArgumentException("Illegal day of week " + dayOfWeek); 708 } 709 if (millis < 0 710 || millis >= Grego.MILLIS_PER_DAY) { 711 throw new IllegalArgumentException("Illegal millis " + millis); 712 } 713 if (monthLength < 28 714 || monthLength > 31) { 715 throw new IllegalArgumentException("Illegal month length " + monthLength); 716 } 717 if (prevMonthLength < 28 718 || prevMonthLength > 31) { 719 throw new IllegalArgumentException("Illegal previous month length " + prevMonthLength); 720 } 721 }*/ 722 723 int result = raw; 724 725 // Bail out if we are before the onset of daylight savings time 726 if (!useDaylight || year < startYear || era != GregorianCalendar.AD) return result; 727 728 // Check for southern hemisphere. We assume that the start and end 729 // month are different. 730 boolean southern = (startMonth > endMonth); 731 732 // Compare the date to the starting and ending rules.+1 = date>rule, -1 733 // = date<rule, 0 = date==rule. 734 int startCompare = compareToRule(month, monthLength, prevMonthLength, 735 day, dayOfWeek, millis, 736 startTimeMode == UTC_TIME ? -raw : 0, 737 startMode, startMonth, startDayOfWeek, 738 startDay, startTime); 739 int endCompare = 0; 740 741 /* We don't always have to compute endCompare. For many instances, 742 * startCompare is enough to determine if we are in DST or not. In the 743 * northern hemisphere, if we are before the start rule, we can't have 744 * DST. In the southern hemisphere, if we are after the start rule, we 745 * must have DST. This is reflected in the way the next if statement 746 * (not the one immediately following) short circuits. */ 747 if (southern != (startCompare >= 0)) { 748 /* For the ending rule comparison, we add the dstSavings to the millis 749 * passed in to convert them from standard to wall time. We then must 750 * normalize the millis to the range 0..millisPerDay-1. */ 751 endCompare = compareToRule(month, monthLength, prevMonthLength, 752 day, dayOfWeek, millis, 753 endTimeMode == WALL_TIME ? dst : 754 (endTimeMode == UTC_TIME ? -raw : 0), 755 endMode, endMonth, endDayOfWeek, 756 endDay, endTime); 757 } 758 759 // Check for both the northern and southern hemisphere cases. We 760 // assume that in the northern hemisphere, the start rule is before the 761 // end rule within the calendar year, and vice versa for the southern 762 // hemisphere. 763 if ((!southern && (startCompare >= 0 && endCompare < 0)) || 764 (southern && (startCompare >= 0 || endCompare < 0))) 765 result += dst; 766 767 return result; 768 } 769 770 /** 771 * {@inheritDoc} 772 * @deprecated This API is ICU internal only. 773 * @hide draft / provisional / internal are hidden on OHOS 774 */ 775 @Override 776 @Deprecated getOffsetFromLocal(long date, int nonExistingTimeOpt, int duplicatedTimeOpt, int[] offsets)777 public void getOffsetFromLocal(long date, 778 int nonExistingTimeOpt, int duplicatedTimeOpt, int[] offsets) { 779 offsets[0] = getRawOffset(); 780 int fields[] = new int[6]; 781 Grego.timeToFields(date, fields); 782 offsets[1] = getOffset(GregorianCalendar.AD, 783 fields[0], fields[1], fields[2], 784 fields[3], fields[5]) - offsets[0]; 785 786 boolean recalc = false; 787 788 // Now, we need some adjustment 789 if (offsets[1] > 0) { 790 if ((nonExistingTimeOpt & STD_DST_MASK) == LOCAL_STD 791 || (nonExistingTimeOpt & STD_DST_MASK) != LOCAL_DST 792 && (nonExistingTimeOpt & FORMER_LATTER_MASK) != LOCAL_LATTER) { 793 date -= getDSTSavings(); 794 recalc = true; 795 } 796 } else { 797 if ((duplicatedTimeOpt & STD_DST_MASK) == LOCAL_DST 798 || (duplicatedTimeOpt & STD_DST_MASK) != LOCAL_STD 799 && (duplicatedTimeOpt & FORMER_LATTER_MASK) == LOCAL_FORMER) { 800 date -= getDSTSavings(); 801 recalc = true; 802 } 803 } 804 805 if (recalc) { 806 Grego.timeToFields(date, fields); 807 offsets[1] = getOffset(GregorianCalendar.AD, 808 fields[0], fields[1], fields[2], 809 fields[3], fields[5]) - offsets[0]; 810 } 811 } 812 813 private static final int 814 DOM_MODE = 1, 815 DOW_IN_MONTH_MODE=2, 816 DOW_GE_DOM_MODE=3, 817 DOW_LE_DOM_MODE=4; 818 819 /** 820 * Compare a given date in the year to a rule. Return 1, 0, or -1, depending 821 * on whether the date is after, equal to, or before the rule date. The 822 * millis are compared directly against the ruleMillis, so any 823 * standard-daylight adjustments must be handled by the caller. 824 * 825 * @return 1 if the date is after the rule date, -1 if the date is before 826 * the rule date, or 0 if the date is equal to the rule date. 827 */ compareToRule(int month, int monthLen, int prevMonthLen, int dayOfMonth, int dayOfWeek, int millis, int millisDelta, int ruleMode, int ruleMonth, int ruleDayOfWeek, int ruleDay, int ruleMillis)828 private int compareToRule(int month, int monthLen, int prevMonthLen, 829 int dayOfMonth, 830 int dayOfWeek, int millis, int millisDelta, 831 int ruleMode, int ruleMonth, int ruleDayOfWeek, 832 int ruleDay, int ruleMillis) 833 { 834 // Make adjustments for startTimeMode and endTimeMode 835 836 millis += millisDelta; 837 838 while (millis >= Grego.MILLIS_PER_DAY) { 839 millis -= Grego.MILLIS_PER_DAY; 840 ++dayOfMonth; 841 dayOfWeek = 1 + (dayOfWeek % 7); // dayOfWeek is one-based 842 if (dayOfMonth > monthLen) { 843 dayOfMonth = 1; 844 /* When incrementing the month, it is desirable to overflow 845 * from DECEMBER to DECEMBER+1, since we use the result to 846 * compare against a real month. Wraparound of the value 847 * leads to bug 4173604. */ 848 ++month; 849 } 850 } 851 /* 852 * For some reasons, Sun Java 6 on Solaris/Linux has a problem with 853 * the while loop below (at least Java 6 up to build 1.6.0_02-b08). 854 * It looks the JRE messes up the variable 'millis' while executing 855 * the code in the while block. The problem is not reproduced with 856 * JVM option -Xint, that is, it is likely a bug of the HotSpot 857 * adaptive compiler. Moving 'millis += Grego.MILLIS_PER_DAY' 858 * to the end of this while block seems to resolve the problem. 859 * See ticket#5887 about the problem in detail. 860 */ 861 while (millis < 0) { 862 //millis += Grego.MILLIS_PER_DAY; 863 --dayOfMonth; 864 dayOfWeek = 1 + ((dayOfWeek+5) % 7); // dayOfWeek is one-based 865 if (dayOfMonth < 1) { 866 dayOfMonth = prevMonthLen; 867 --month; 868 } 869 millis += Grego.MILLIS_PER_DAY; 870 } 871 872 if (month < ruleMonth) return -1; 873 else if (month > ruleMonth) return 1; 874 875 int ruleDayOfMonth = 0; 876 877 // Adjust the ruleDay to the monthLen, for non-leap year February 29 rule days. 878 if (ruleDay > monthLen) { 879 ruleDay = monthLen; 880 } 881 882 switch (ruleMode) 883 { 884 case DOM_MODE: 885 ruleDayOfMonth = ruleDay; 886 break; 887 case DOW_IN_MONTH_MODE: 888 // In this case ruleDay is the day-of-week-in-month 889 if (ruleDay > 0) 890 ruleDayOfMonth = 1 + (ruleDay - 1) * 7 + 891 (7 + ruleDayOfWeek - (dayOfWeek - dayOfMonth + 1)) % 7; 892 else // Assume ruleDay < 0 here 893 { 894 ruleDayOfMonth = monthLen + (ruleDay + 1) * 7 - 895 (7 + (dayOfWeek + monthLen - dayOfMonth) - ruleDayOfWeek) % 7; 896 } 897 break; 898 case DOW_GE_DOM_MODE: 899 ruleDayOfMonth = ruleDay + 900 (49 + ruleDayOfWeek - ruleDay - dayOfWeek + dayOfMonth) % 7; 901 break; 902 case DOW_LE_DOM_MODE: 903 ruleDayOfMonth = ruleDay - 904 (49 - ruleDayOfWeek + ruleDay + dayOfWeek - dayOfMonth) % 7; 905 // Note at this point ruleDayOfMonth may be <1, although it will 906 // be >=1 for well-formed rules. 907 break; 908 } 909 910 if (dayOfMonth < ruleDayOfMonth) return -1; 911 else if (dayOfMonth > ruleDayOfMonth) return 1; 912 913 if (millis < ruleMillis){ 914 return -1; 915 }else if (millis > ruleMillis){ 916 return 1; 917 }else{ 918 return 0; 919 } 920 } 921 922 // data needed for streaming mutated SimpleTimeZones in JDK14 923 private int raw;// the TimeZone's raw GMT offset 924 private int dst = 3600000; 925 private STZInfo xinfo = null; 926 private int startMonth, startDay, startDayOfWeek; // the month, day, DOW, and time DST starts 927 private int startTime; 928 private int startTimeMode, endTimeMode; // Mode for startTime, endTime; see TimeMode 929 private int endMonth, endDay, endDayOfWeek; // the month, day, DOW, and time DST ends 930 private int endTime; 931 private int startYear; // the year these DST rules took effect 932 private boolean useDaylight; // flag indicating whether this TimeZone uses DST 933 private int startMode, endMode; // flags indicating what kind of rules the DST rules are 934 935 /** 936 * Overrides TimeZone 937 * Queries if this time zone uses Daylight Saving Time. 938 */ 939 @Override useDaylightTime()940 public boolean useDaylightTime(){ 941 return useDaylight; 942 } 943 944 /** 945 * {@inheritDoc} 946 */ 947 @Override observesDaylightTime()948 public boolean observesDaylightTime() { 949 return useDaylight; 950 } 951 952 /** 953 * Overrides TimeZone 954 * Queries if the give date is in Daylight Saving Time. 955 */ 956 @Override inDaylightTime(Date date)957 public boolean inDaylightTime(Date date){ 958 GregorianCalendar gc = new GregorianCalendar(this); 959 gc.setTime(date); 960 return gc.inDaylightTime(); 961 } 962 963 /** 964 * Internal construction method. 965 */ construct(int _raw, int _startMonth, int _startDay, int _startDayOfWeek, int _startTime, int _startTimeMode, int _endMonth, int _endDay, int _endDayOfWeek, int _endTime, int _endTimeMode, int _dst)966 private void construct(int _raw, 967 int _startMonth, 968 int _startDay, 969 int _startDayOfWeek, 970 int _startTime, 971 int _startTimeMode, 972 int _endMonth, 973 int _endDay, 974 int _endDayOfWeek, 975 int _endTime, 976 int _endTimeMode, 977 int _dst) { 978 raw = _raw; 979 startMonth = _startMonth; 980 startDay = _startDay; 981 startDayOfWeek = _startDayOfWeek; 982 startTime = _startTime; 983 startTimeMode = _startTimeMode; 984 endMonth = _endMonth; 985 endDay = _endDay; 986 endDayOfWeek = _endDayOfWeek; 987 endTime = _endTime; 988 endTimeMode = _endTimeMode; 989 dst = _dst; 990 startYear = 0; 991 startMode = DOM_MODE; 992 endMode = DOM_MODE; 993 994 decodeRules(); 995 996 if (_dst == 0) { 997 throw new IllegalArgumentException(); 998 } 999 } decodeRules()1000 private void decodeRules(){ 1001 decodeStartRule(); 1002 decodeEndRule(); 1003 } 1004 1005 /** 1006 * Decode the start rule and validate the parameters. The parameters are 1007 * expected to be in encoded form, which represents the various rule modes 1008 * by negating or zeroing certain values. Representation formats are: 1009 * <p> 1010 * <pre> 1011 * DOW_IN_MONTH DOM DOW>=DOM DOW<=DOM no DST 1012 * ------------ ----- -------- -------- ---------- 1013 * month 0..11 same same same don't care 1014 * day -5..5 1..31 1..31 -1..-31 0 1015 * dayOfWeek 1..7 0 -1..-7 -1..-7 don't care 1016 * time 0..ONEDAY same same same don't care 1017 * </pre> 1018 * The range for month does not include UNDECIMBER since this class is 1019 * really specific to GregorianCalendar, which does not use that month. 1020 * The range for time includes ONEDAY (vs. ending at ONEDAY-1) because the 1021 * end rule is an exclusive limit point. That is, the range of times that 1022 * are in DST include those >= the start and < the end. For this reason, 1023 * it should be possible to specify an end of ONEDAY in order to include the 1024 * entire day. Although this is equivalent to time 0 of the following day, 1025 * it's not always possible to specify that, for example, on December 31. 1026 * While arguably the start range should still be 0..ONEDAY-1, we keep 1027 * the start and end ranges the same for consistency. 1028 */ decodeStartRule()1029 private void decodeStartRule() { 1030 useDaylight = (startDay != 0) && (endDay != 0); 1031 if (useDaylight && dst == 0) { 1032 dst = Grego.MILLIS_PER_DAY; 1033 } 1034 if (startDay != 0) { 1035 if (startMonth < Calendar.JANUARY || startMonth > Calendar.DECEMBER) { 1036 throw new IllegalArgumentException(); 1037 } 1038 if (startTime < 0 || startTime > Grego.MILLIS_PER_DAY || 1039 startTimeMode < WALL_TIME || startTimeMode > UTC_TIME) { 1040 throw new IllegalArgumentException(); 1041 } 1042 if (startDayOfWeek == 0) { 1043 startMode = DOM_MODE; 1044 } else { 1045 if (startDayOfWeek > 0) { 1046 startMode = DOW_IN_MONTH_MODE; 1047 } else { 1048 startDayOfWeek = -startDayOfWeek; 1049 if (startDay > 0) { 1050 startMode = DOW_GE_DOM_MODE; 1051 } else { 1052 startDay = -startDay; 1053 startMode = DOW_LE_DOM_MODE; 1054 } 1055 } 1056 if (startDayOfWeek > Calendar.SATURDAY) { 1057 throw new IllegalArgumentException(); 1058 } 1059 } 1060 if (startMode == DOW_IN_MONTH_MODE) { 1061 if (startDay < -5 || startDay > 5) { 1062 throw new IllegalArgumentException(); 1063 } 1064 } else if (startDay < 1 || startDay > staticMonthLength[startMonth]) { 1065 throw new IllegalArgumentException(); 1066 } 1067 } 1068 } 1069 1070 /** 1071 * Decode the end rule and validate the parameters. This method is exactly 1072 * analogous to decodeStartRule(). 1073 * @see #decodeStartRule 1074 */ decodeEndRule()1075 private void decodeEndRule() { 1076 useDaylight = (startDay != 0) && (endDay != 0); 1077 if (useDaylight && dst == 0) { 1078 dst = Grego.MILLIS_PER_DAY; 1079 } 1080 if (endDay != 0) { 1081 if (endMonth < Calendar.JANUARY || endMonth > Calendar.DECEMBER) { 1082 throw new IllegalArgumentException(); 1083 } 1084 if (endTime < 0 || endTime > Grego.MILLIS_PER_DAY || 1085 endTimeMode < WALL_TIME || endTimeMode > UTC_TIME) { 1086 throw new IllegalArgumentException(); 1087 } 1088 if (endDayOfWeek == 0) { 1089 endMode = DOM_MODE; 1090 } else { 1091 if (endDayOfWeek > 0) { 1092 endMode = DOW_IN_MONTH_MODE; 1093 } else { 1094 endDayOfWeek = -endDayOfWeek; 1095 if (endDay > 0) { 1096 endMode = DOW_GE_DOM_MODE; 1097 } else { 1098 endDay = -endDay; 1099 endMode = DOW_LE_DOM_MODE; 1100 } 1101 } 1102 if (endDayOfWeek > Calendar.SATURDAY) { 1103 throw new IllegalArgumentException(); 1104 } 1105 } 1106 if (endMode == DOW_IN_MONTH_MODE) { 1107 if (endDay < -5 || endDay > 5) { 1108 throw new IllegalArgumentException(); 1109 } 1110 } else if (endDay<1 || endDay > staticMonthLength[endMonth]) { 1111 throw new IllegalArgumentException(); 1112 } 1113 } 1114 } 1115 1116 /** 1117 * Overrides equals. 1118 * @return true if obj is a SimpleTimeZone equivalent to this 1119 */ 1120 @Override equals(Object obj)1121 public boolean equals(Object obj){ 1122 if (this == obj) return true; 1123 if (obj == null || getClass() != obj.getClass()) return false; 1124 SimpleTimeZone that = (SimpleTimeZone) obj; 1125 return raw == that.raw && 1126 useDaylight == that.useDaylight && 1127 idEquals(getID(),that.getID()) && 1128 (!useDaylight 1129 // Only check rules if using DST 1130 || (dst == that.dst && 1131 startMode == that.startMode && 1132 startMonth == that.startMonth && 1133 startDay == that.startDay && 1134 startDayOfWeek == that.startDayOfWeek && 1135 startTime == that.startTime && 1136 startTimeMode == that.startTimeMode && 1137 endMode == that.endMode && 1138 endMonth == that.endMonth && 1139 endDay == that.endDay && 1140 endDayOfWeek == that.endDayOfWeek && 1141 endTime == that.endTime && 1142 endTimeMode == that.endTimeMode && 1143 startYear == that.startYear )); 1144 1145 } idEquals(String id1, String id2)1146 private boolean idEquals(String id1, String id2){ 1147 if(id1==null && id2==null){ 1148 return true; 1149 } 1150 if(id1!=null && id2!=null){ 1151 return id1.equals(id2); 1152 } 1153 return false; 1154 } 1155 1156 /** 1157 * Overrides hashCode. 1158 * @return a hash code value for this object. 1159 */ 1160 @Override hashCode()1161 public int hashCode(){ 1162 int ret = super.hashCode() 1163 + raw ^ (raw >>> 8) 1164 + (useDaylight ? 0 : 1); 1165 if(!useDaylight){ 1166 ret += dst ^ (dst >>> 10) + 1167 startMode ^ (startMode>>>11) + 1168 startMonth ^ (startMonth>>>12) + 1169 startDay ^ (startDay>>>13) + 1170 startDayOfWeek ^ (startDayOfWeek>>>14) + 1171 startTime ^ (startTime>>>15) + 1172 startTimeMode ^ (startTimeMode>>>16) + 1173 endMode ^ (endMode>>>17) + 1174 endMonth ^ (endMonth>>>18) + 1175 endDay ^ (endDay>>>19) + 1176 endDayOfWeek ^ (endDayOfWeek>>>20) + 1177 endTime ^ (endTime>>>21) + 1178 endTimeMode ^ (endTimeMode>>>22) + 1179 startYear ^ (startYear>>>23); 1180 } 1181 return ret; 1182 } 1183 1184 /** 1185 * Overrides clone. 1186 */ 1187 @Override clone()1188 public Object clone() { 1189 if (isFrozen()) { 1190 return this; 1191 } 1192 return cloneAsThawed(); 1193 } 1194 1195 /** 1196 * Returns true if this zone has the same rules and offset as another zone. 1197 * @param othr the TimeZone object to be compared with 1198 * @return true if the given zone has the same rules and offset as this one 1199 */ 1200 @Override hasSameRules(TimeZone othr)1201 public boolean hasSameRules(TimeZone othr) { 1202 if (this == othr) { 1203 return true; 1204 } 1205 if(!(othr instanceof SimpleTimeZone)){ 1206 return false; 1207 } 1208 SimpleTimeZone other = (SimpleTimeZone)othr; 1209 return other != null && 1210 raw == other.raw && 1211 useDaylight == other.useDaylight && 1212 (!useDaylight 1213 // Only check rules if using DST 1214 || (dst == other.dst && 1215 startMode == other.startMode && 1216 startMonth == other.startMonth && 1217 startDay == other.startDay && 1218 startDayOfWeek == other.startDayOfWeek && 1219 startTime == other.startTime && 1220 startTimeMode == other.startTimeMode && 1221 endMode == other.endMode && 1222 endMonth == other.endMonth && 1223 endDay == other.endDay && 1224 endDayOfWeek == other.endDayOfWeek && 1225 endTime == other.endTime && 1226 endTimeMode == other.endTimeMode && 1227 startYear == other.startYear)); 1228 } 1229 1230 // BasicTimeZone methods 1231 1232 /** 1233 * {@inheritDoc} 1234 */ 1235 @Override getNextTransition(long base, boolean inclusive)1236 public TimeZoneTransition getNextTransition(long base, boolean inclusive) { 1237 if (!useDaylight) { 1238 return null; 1239 } 1240 1241 initTransitionRules(); 1242 long firstTransitionTime = firstTransition.getTime(); 1243 if (base < firstTransitionTime || (inclusive && base == firstTransitionTime)) { 1244 return firstTransition; 1245 } 1246 Date stdDate = stdRule.getNextStart(base, dstRule.getRawOffset(), dstRule.getDSTSavings(), 1247 inclusive); 1248 Date dstDate = dstRule.getNextStart(base, stdRule.getRawOffset(), stdRule.getDSTSavings(), 1249 inclusive); 1250 if (stdDate != null && (dstDate == null || stdDate.before(dstDate))) { 1251 return new TimeZoneTransition(stdDate.getTime(), dstRule, stdRule); 1252 } 1253 if (dstDate != null && (stdDate == null || dstDate.before(stdDate))) { 1254 return new TimeZoneTransition(dstDate.getTime(), stdRule, dstRule); 1255 } 1256 return null; 1257 } 1258 1259 /** 1260 * {@inheritDoc} 1261 */ 1262 @Override getPreviousTransition(long base, boolean inclusive)1263 public TimeZoneTransition getPreviousTransition(long base, boolean inclusive) { 1264 if (!useDaylight) { 1265 return null; 1266 } 1267 1268 initTransitionRules(); 1269 long firstTransitionTime = firstTransition.getTime(); 1270 if (base < firstTransitionTime || (!inclusive && base == firstTransitionTime)) { 1271 return null; 1272 } 1273 Date stdDate = stdRule.getPreviousStart(base, dstRule.getRawOffset(), 1274 dstRule.getDSTSavings(), inclusive); 1275 Date dstDate = dstRule.getPreviousStart(base, stdRule.getRawOffset(), 1276 stdRule.getDSTSavings(), inclusive); 1277 if (stdDate != null && (dstDate == null || stdDate.after(dstDate))) { 1278 return new TimeZoneTransition(stdDate.getTime(), dstRule, stdRule); 1279 } 1280 if (dstDate != null && (stdDate == null || dstDate.after(stdDate))) { 1281 return new TimeZoneTransition(dstDate.getTime(), stdRule, dstRule); 1282 } 1283 return null; 1284 } 1285 1286 /** 1287 * {@inheritDoc} 1288 */ 1289 @Override getTimeZoneRules()1290 public TimeZoneRule[] getTimeZoneRules() { 1291 initTransitionRules(); 1292 1293 int size = useDaylight ? 3 : 1; 1294 TimeZoneRule[] rules = new TimeZoneRule[size]; 1295 rules[0] = initialRule; 1296 if (useDaylight) { 1297 rules[1] = stdRule; 1298 rules[2] = dstRule; 1299 } 1300 return rules; 1301 } 1302 1303 private transient boolean transitionRulesInitialized; 1304 private transient InitialTimeZoneRule initialRule; 1305 private transient TimeZoneTransition firstTransition; 1306 private transient AnnualTimeZoneRule stdRule; 1307 private transient AnnualTimeZoneRule dstRule; 1308 initTransitionRules()1309 private synchronized void initTransitionRules() { 1310 if (transitionRulesInitialized) { 1311 return; 1312 } 1313 if (useDaylight) { 1314 DateTimeRule dtRule = null; 1315 int timeRuleType; 1316 long firstStdStart, firstDstStart; 1317 1318 // Create a TimeZoneRule for daylight saving time 1319 timeRuleType = (startTimeMode == STANDARD_TIME) ? DateTimeRule.STANDARD_TIME : 1320 ((startTimeMode == UTC_TIME) ? DateTimeRule.UTC_TIME : DateTimeRule.WALL_TIME); 1321 switch (startMode) { 1322 case DOM_MODE: 1323 dtRule = new DateTimeRule(startMonth, startDay, startTime, timeRuleType); 1324 break; 1325 case DOW_IN_MONTH_MODE: 1326 dtRule = new DateTimeRule(startMonth, startDay, startDayOfWeek, startTime, 1327 timeRuleType); 1328 break; 1329 case DOW_GE_DOM_MODE: 1330 dtRule = new DateTimeRule(startMonth, startDay, startDayOfWeek, true, startTime, 1331 timeRuleType); 1332 break; 1333 case DOW_LE_DOM_MODE: 1334 dtRule = new DateTimeRule(startMonth, startDay, startDayOfWeek, false, startTime, 1335 timeRuleType); 1336 break; 1337 } 1338 // For now, use ID + "(DST)" as the name 1339 dstRule = new AnnualTimeZoneRule(getID() + "(DST)", getRawOffset(), getDSTSavings(), 1340 dtRule, startYear, AnnualTimeZoneRule.MAX_YEAR); 1341 1342 // Calculate the first DST start time 1343 firstDstStart = dstRule.getFirstStart(getRawOffset(), 0).getTime(); 1344 1345 // Create a TimeZoneRule for standard time 1346 timeRuleType = (endTimeMode == STANDARD_TIME) ? DateTimeRule.STANDARD_TIME : 1347 ((endTimeMode == UTC_TIME) ? DateTimeRule.UTC_TIME : DateTimeRule.WALL_TIME); 1348 switch (endMode) { 1349 case DOM_MODE: 1350 dtRule = new DateTimeRule(endMonth, endDay, endTime, timeRuleType); 1351 break; 1352 case DOW_IN_MONTH_MODE: 1353 dtRule = new DateTimeRule(endMonth, endDay, endDayOfWeek, endTime, timeRuleType); 1354 break; 1355 case DOW_GE_DOM_MODE: 1356 dtRule = new DateTimeRule(endMonth, endDay, endDayOfWeek, true, endTime, 1357 timeRuleType); 1358 break; 1359 case DOW_LE_DOM_MODE: 1360 dtRule = new DateTimeRule(endMonth, endDay, endDayOfWeek, false, endTime, 1361 timeRuleType); 1362 break; 1363 } 1364 // For now, use ID + "(STD)" as the name 1365 stdRule = new AnnualTimeZoneRule(getID() + "(STD)", getRawOffset(), 0, 1366 dtRule, startYear, AnnualTimeZoneRule.MAX_YEAR); 1367 1368 // Calculate the first STD start time 1369 firstStdStart = stdRule.getFirstStart(getRawOffset(), dstRule.getDSTSavings()).getTime(); 1370 1371 // Create a TimeZoneRule for initial time 1372 if (firstStdStart < firstDstStart) { 1373 initialRule = new InitialTimeZoneRule(getID() + "(DST)", getRawOffset(), 1374 dstRule.getDSTSavings()); 1375 firstTransition = new TimeZoneTransition(firstStdStart, initialRule, stdRule); 1376 } else { 1377 initialRule = new InitialTimeZoneRule(getID() + "(STD)", getRawOffset(), 0); 1378 firstTransition = new TimeZoneTransition(firstDstStart, initialRule, dstRule); 1379 } 1380 1381 } else { 1382 // Create a TimeZoneRule for initial time 1383 initialRule = new InitialTimeZoneRule(getID(), getRawOffset(), 0); 1384 } 1385 transitionRulesInitialized = true; 1386 } 1387 1388 // Freezable stuffs 1389 private volatile transient boolean isFrozen = false; 1390 1391 /** 1392 * {@inheritDoc} 1393 */ 1394 @Override isFrozen()1395 public boolean isFrozen() { 1396 return isFrozen; 1397 } 1398 1399 /** 1400 * {@inheritDoc} 1401 */ 1402 @Override freeze()1403 public TimeZone freeze() { 1404 isFrozen = true; 1405 return this; 1406 } 1407 1408 /** 1409 * {@inheritDoc} 1410 */ 1411 @Override cloneAsThawed()1412 public TimeZone cloneAsThawed() { 1413 SimpleTimeZone tz = (SimpleTimeZone)super.cloneAsThawed(); 1414 tz.isFrozen = false; 1415 return tz; 1416 } 1417 } 1418