1 /* 2 * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 /* 25 * @test 26 * @bug 4052967 4073209 4073215 4084933 4096952 4109314 4126678 4151406 4151429 27 * 4154525 4154537 4154542 4154650 4159922 4162593 4173604 4176686 4184229 4208960 28 * 4966229 6433179 6851214 8007520 8008577 29 * @library /java/text/testlib 30 * @run main/othervm -Djava.locale.providers=COMPAT,SPI TimeZoneRegression 31 */ 32 33 import java.util.*; 34 import java.io.*; 35 import java.text.*; 36 37 public class TimeZoneRegression extends IntlTest { 38 main(String[] args)39 public static void main(String[] args) throws Exception { 40 new TimeZoneRegression().run(args); 41 } 42 Test4073209()43 public void Test4073209() { 44 TimeZone z1 = TimeZone.getTimeZone("PST"); 45 TimeZone z2 = TimeZone.getTimeZone("PST"); 46 if (z1 == z2) { 47 errln("Fail: TimeZone should return clones"); 48 } 49 } 50 51 @SuppressWarnings("deprecation") Test4073215()52 public void Test4073215() { 53 SimpleTimeZone z = new SimpleTimeZone(0, "GMT"); 54 if (z.useDaylightTime()) { 55 errln("Fail: Fix test to start with non-DST zone"); 56 } 57 z.setStartRule(Calendar.FEBRUARY, 1, Calendar.SUNDAY, 0); 58 z.setEndRule(Calendar.MARCH, -1, Calendar.SUNDAY, 0); 59 if (!z.useDaylightTime()) { 60 errln("Fail: DST not active"); 61 } 62 if (z.inDaylightTime(new Date(97, Calendar.JANUARY, 31)) || 63 !z.inDaylightTime(new Date(97, Calendar.MARCH, 1)) || 64 z.inDaylightTime(new Date(97, Calendar.MARCH, 31))) { 65 errln("Fail: DST not working as expected"); 66 } 67 } 68 69 /** 70 * The expected behavior of TimeZone around the boundaries is: 71 * (Assume transition time of 2:00 AM) 72 * day of onset 1:59 AM STD = display name 1:59 AM ST 73 * 2:00 AM STD = display name 3:00 AM DT 74 * day of end 0:59 AM STD = display name 1:59 AM DT 75 * 1:00 AM STD = display name 1:00 AM ST 76 */ Test4084933()77 public void Test4084933() { 78 // test both SimpleTimeZone and ZoneInfo objects. 79 // @since 1.4 80 sub4084933(getPST()); 81 sub4084933(TimeZone.getTimeZone("PST")); 82 } 83 sub4084933(TimeZone tz)84 private void sub4084933(TimeZone tz) { 85 long offset1 = tz.getOffset(1, 86 1997, Calendar.OCTOBER, 26, Calendar.SUNDAY, (2*60*60*1000)); 87 long offset2 = tz.getOffset(1, 88 1997, Calendar.OCTOBER, 26, Calendar.SUNDAY, (2*60*60*1000)-1); 89 90 long offset3 = tz.getOffset(1, 91 1997, Calendar.OCTOBER, 26, Calendar.SUNDAY, (1*60*60*1000)); 92 long offset4 = tz.getOffset(1, 93 1997, Calendar.OCTOBER, 26, Calendar.SUNDAY, (1*60*60*1000)-1); 94 95 /* 96 * The following was added just for consistency. It shows that going *to* Daylight 97 * Savings Time (PDT) does work at 2am. 98 */ 99 100 long offset5 = tz.getOffset(1, 101 1997, Calendar.APRIL, 6, Calendar.SUNDAY, (2*60*60*1000)); 102 long offset6 = tz.getOffset(1, 103 1997, Calendar.APRIL, 6, Calendar.SUNDAY, (2*60*60*1000)-1); 104 105 long offset7 = tz.getOffset(1, 106 1997, Calendar.APRIL, 6, Calendar.SUNDAY, (1*60*60*1000)); 107 long offset8 = tz.getOffset(1, 108 1997, Calendar.APRIL, 6, Calendar.SUNDAY, (1*60*60*1000)-1); 109 110 long SToffset = -8 * 60*60*1000L; 111 long DToffset = -7 * 60*60*1000L; 112 if (offset1 != SToffset || offset2 != SToffset || 113 offset3 != SToffset || offset4 != DToffset || 114 offset5 != DToffset || offset6 != SToffset || 115 offset7 != SToffset || offset8 != SToffset) 116 errln("Fail: TimeZone misbehaving"); { 117 } 118 } 119 Test4096952()120 public void Test4096952() { 121 String[] ZONES = { "GMT", "MET", "IST" }; 122 boolean pass = true; 123 try { 124 for (int i=0; i<ZONES.length; ++i) { 125 TimeZone zone = TimeZone.getTimeZone(ZONES[i]); 126 if (!zone.getID().equals(ZONES[i])) 127 errln("Fail: Test broken; zones not instantiating"); 128 129 ByteArrayOutputStream baos; 130 ObjectOutputStream ostream = 131 new ObjectOutputStream(baos = new 132 ByteArrayOutputStream()); 133 ostream.writeObject(zone); 134 ostream.close(); 135 baos.close(); 136 ObjectInputStream istream = 137 new ObjectInputStream(new 138 ByteArrayInputStream(baos.toByteArray())); 139 TimeZone frankenZone = (TimeZone) istream.readObject(); 140 //logln("Zone: " + zone); 141 //logln("FrankenZone: " + frankenZone); 142 if (!zone.equals(frankenZone)) { 143 logln("TimeZone " + zone.getID() + 144 " not equal to serialized/deserialized one"); 145 pass = false; 146 } 147 } 148 if (!pass) errln("Fail: TimeZone serialization/equality bug"); 149 } 150 catch (IOException e) { 151 errln("Fail: " + e); 152 e.printStackTrace(); 153 } 154 catch (ClassNotFoundException e) { 155 errln("Fail: " + e); 156 e.printStackTrace(); 157 } 158 } 159 Test4109314()160 public void Test4109314() { 161 Locale locale = Locale.getDefault(); 162 if (!TestUtils.usesGregorianCalendar(locale)) { 163 logln("Skipping this test because locale is " + locale); 164 return; 165 } 166 167 // test both SimpleTimeZone and ZoneInfo objects. 168 // @since 1.4 169 sub4109314(getPST()); 170 sub4109314(TimeZone.getTimeZone("PST")); 171 } 172 173 174 @SuppressWarnings("deprecation") sub4109314(TimeZone PST)175 private void sub4109314(TimeZone PST) { 176 GregorianCalendar testCal = (GregorianCalendar)Calendar.getInstance(); 177 Object[] testData = { 178 PST, new Date(98,Calendar.APRIL,4,22,0), new Date(98, Calendar.APRIL, 5,6,0), 179 PST, new Date(98,Calendar.OCTOBER,24,22,0), new Date(98,Calendar.OCTOBER,25,6,0), 180 }; 181 boolean pass=true; 182 for (int i=0; i<testData.length; i+=3) { 183 testCal.setTimeZone((TimeZone) testData[i]); 184 long t = ((Date)testData[i+1]).getTime(); 185 Date end = (Date) testData[i+2]; 186 while (t < end.getTime()) { 187 testCal.setTime(new Date(t)); 188 if (!checkCalendar314(testCal, (TimeZone) testData[i])) 189 pass = false; 190 t += 60*60*1000L; 191 } 192 } 193 if (!pass) errln("Fail: TZ API inconsistent"); 194 } 195 checkCalendar314(GregorianCalendar testCal, TimeZone testTZ)196 boolean checkCalendar314(GregorianCalendar testCal, TimeZone testTZ) { 197 // GregorianCalendar testCal = (GregorianCalendar)aCal.clone(); 198 199 final int ONE_DAY = 24*60*60*1000; 200 201 int tzOffset, tzRawOffset; 202 Float tzOffsetFloat,tzRawOffsetFloat; 203 // Here is where the user made an error. They were passing in the value of 204 // the MILLSECOND field; you need to pass in the millis in the day in STANDARD 205 // time. 206 int millis = testCal.get(Calendar.MILLISECOND) + 207 1000 * (testCal.get(Calendar.SECOND) + 208 60 * (testCal.get(Calendar.MINUTE) + 209 60 * (testCal.get(Calendar.HOUR_OF_DAY)))) - 210 testCal.get(Calendar.DST_OFFSET); 211 212 /* Fix up millis to be in range. ASSUME THAT WE ARE NOT AT THE 213 * BEGINNING OR END OF A MONTH. We must add this code because 214 * getOffset() has been changed to be more strict about the parameters 215 * it receives -- it turns out that this test was passing in illegal 216 * values. */ 217 int date = testCal.get(Calendar.DATE); 218 int dow = testCal.get(Calendar.DAY_OF_WEEK); 219 while (millis < 0) { 220 millis += ONE_DAY; 221 --date; 222 dow = Calendar.SUNDAY + ((dow - Calendar.SUNDAY + 6) % 7); 223 } 224 while (millis >= ONE_DAY) { 225 millis -= ONE_DAY; 226 ++date; 227 dow = Calendar.SUNDAY + ((dow - Calendar.SUNDAY + 1) % 7); 228 } 229 230 tzOffset = testTZ.getOffset(testCal.get(Calendar.ERA), 231 testCal.get(Calendar.YEAR), 232 testCal.get(Calendar.MONTH), 233 date, 234 dow, 235 millis); 236 tzRawOffset = testTZ.getRawOffset(); 237 tzOffsetFloat = new Float((float)tzOffset/(float)3600000); 238 tzRawOffsetFloat = new Float((float)tzRawOffset/(float)3600000); 239 240 Date testDate = testCal.getTime(); 241 242 boolean inDaylightTime = testTZ.inDaylightTime(testDate); 243 SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy HH:mm"); 244 sdf.setCalendar(testCal); 245 String inDaylightTimeString; 246 247 boolean passed; 248 249 if (inDaylightTime) 250 { 251 inDaylightTimeString = " DST "; 252 passed = (tzOffset == (tzRawOffset + 3600000)); 253 } 254 else 255 { 256 inDaylightTimeString = " "; 257 passed = (tzOffset == tzRawOffset); 258 } 259 260 String output = testTZ.getID() + " " + sdf.format(testDate) + 261 " Offset(" + tzOffsetFloat + ")" + 262 " RawOffset(" + tzRawOffsetFloat + ")" + 263 " " + millis/(float)3600000 + " " + 264 inDaylightTimeString; 265 266 if (passed) 267 output += " "; 268 else 269 output += "ERROR"; 270 271 if (passed) logln(output); else errln(output); 272 return passed; 273 } 274 275 /** 276 * CANNOT REPRODUDE 277 * 278 * Yet another _alleged_ bug in TimeZone.getOffset(), a method that never 279 * should have been made public. It's simply too hard to use correctly. 280 * 281 * The original test code failed to do the following: 282 * (1) Call Calendar.setTime() before getting the fields! 283 * (2) Use the right millis (as usual) for getOffset(); they were passing 284 * in the MILLIS field, instead of the STANDARD MILLIS IN DAY. 285 * When you fix these two problems, the test passes, as expected. 286 */ Test4126678()287 public void Test4126678() { 288 Locale locale = Locale.getDefault(); 289 if (!TestUtils.usesGregorianCalendar(locale)) { 290 logln("Skipping this test because locale is " + locale); 291 return; 292 } 293 294 // Note: this test depends on the PST time zone. 295 TimeZone initialZone = TimeZone.getDefault(); 296 297 // test both SimpleTimeZone and ZoneInfo objects. 298 // @since 1.4 299 sub4126678(getPST()); 300 sub4126678(TimeZone.getTimeZone("PST")); 301 302 // restore the initial time zone so that this test case 303 // doesn't affect the others. 304 TimeZone.setDefault(initialZone); 305 } 306 307 @SuppressWarnings("deprecation") sub4126678(TimeZone tz)308 private void sub4126678(TimeZone tz) { 309 Calendar cal = Calendar.getInstance(); 310 TimeZone.setDefault(tz); 311 cal.setTimeZone(tz); 312 313 Date dt = new Date(1998-1900, Calendar.APRIL, 5, 10, 0); 314 // the dt value is local time in PST. 315 if (!tz.inDaylightTime(dt)) 316 errln("We're not in Daylight Savings Time and we should be.\n"); 317 318 cal.setTime(dt); 319 int era = cal.get(Calendar.ERA); 320 int year = cal.get(Calendar.YEAR); 321 int month = cal.get(Calendar.MONTH); 322 int day = cal.get(Calendar.DATE); 323 int dayOfWeek = cal.get(Calendar.DAY_OF_WEEK); 324 int millis = cal.get(Calendar.MILLISECOND) + 325 (cal.get(Calendar.SECOND) + 326 (cal.get(Calendar.MINUTE) + 327 (cal.get(Calendar.HOUR) * 60) * 60) * 1000) - 328 cal.get(Calendar.DST_OFFSET); 329 330 long offset = tz.getOffset(era, year, month, day, dayOfWeek, millis); 331 long raw_offset = tz.getRawOffset(); 332 if (offset == raw_offset) { 333 errln("Offsets should not match when in DST"); 334 } 335 } 336 337 /** 338 * TimeZone.getAvailableIDs(int) throws exception for certain values, 339 * due to a faulty constant in TimeZone.java. 340 */ Test4151406()341 public void Test4151406() { 342 int max = 0; 343 for (int h=-28; h<=30; ++h) { 344 // h is in half-hours from GMT; rawoffset is in millis 345 int rawoffset = h * 1800000; 346 int hh = (h<0) ? -h : h; 347 String hname = ((h<0) ? "GMT-" : "GMT+") + 348 ((hh/2 < 10) ? "0" : "") + 349 (hh/2) + ':' + 350 ((hh%2==0) ? "00" : "30"); 351 try { 352 String[] ids = TimeZone.getAvailableIDs(rawoffset); 353 if (ids.length > max) max = ids.length; 354 logln(hname + ' ' + ids.length + 355 ((ids.length > 0) ? (" e.g. " + ids[0]) : "")); 356 } catch (Exception e) { 357 errln(hname + ' ' + "Fail: " + e); 358 } 359 } 360 logln("Maximum zones per offset = " + max); 361 } 362 Test4151429()363 public void Test4151429() { 364 try { 365 TimeZone tz = TimeZone.getTimeZone("GMT"); 366 String name = tz.getDisplayName(true, Integer.MAX_VALUE, 367 Locale.getDefault()); 368 errln("IllegalArgumentException not thrown by TimeZone.getDisplayName()"); 369 } catch(IllegalArgumentException e) {} 370 } 371 372 /** 373 * SimpleTimeZone accepts illegal DST savings values. These values 374 * must be non-zero. There is no upper limit at this time. 375 */ Test4154525()376 public void Test4154525() { 377 final int GOOD = 1, BAD = 0; 378 int[] DATA = { 379 1, GOOD, 380 0, BAD, 381 -1, BAD, 382 60*60*1000, GOOD, 383 Integer.MIN_VALUE, BAD, 384 // Integer.MAX_VALUE, ?, // no upper limit on DST savings at this time 385 }; 386 for (int i=0; i<DATA.length; i+=2) { 387 int savings = DATA[i]; 388 boolean valid = DATA[i+1] == GOOD; 389 String method = null; 390 for (int j=0; j<2; ++j) { 391 try { 392 switch (j) { 393 case 0: 394 method = "constructor"; 395 SimpleTimeZone z = new SimpleTimeZone(0, "id", 396 Calendar.JANUARY, 1, 0, 0, 397 Calendar.MARCH, 1, 0, 0, 398 savings); // <- what we're interested in 399 break; 400 case 1: 401 method = "setDSTSavings()"; 402 z = new SimpleTimeZone(0, "GMT"); 403 z.setDSTSavings(savings); 404 break; 405 } 406 if (valid) { 407 logln("Pass: DST savings of " + savings + " accepted by " + method); 408 } else { 409 errln("Fail: DST savings of " + savings + " accepted by " + method); 410 } 411 } catch (IllegalArgumentException e) { 412 if (valid) { 413 errln("Fail: DST savings of " + savings + " to " + method + " gave " + e); 414 } else { 415 logln("Pass: DST savings of " + savings + " to " + method + " gave " + e); 416 } 417 } 418 } 419 } 420 } 421 422 /** 423 * SimpleTimeZone.hasSameRules() doesn't work for zones with no DST 424 * and different DST parameters. 425 */ Test4154537()426 public void Test4154537() { 427 // tz1 and tz2 have no DST and different rule parameters 428 SimpleTimeZone tz1 = new SimpleTimeZone(0, "1", 0, 0, 0, 0, 2, 0, 0, 0); 429 SimpleTimeZone tz2 = new SimpleTimeZone(0, "2", 1, 0, 0, 0, 3, 0, 0, 0); 430 // tza and tzA have the same rule params 431 SimpleTimeZone tza = new SimpleTimeZone(0, "a", 0, 1, 0, 0, 3, 2, 0, 0); 432 SimpleTimeZone tzA = new SimpleTimeZone(0, "A", 0, 1, 0, 0, 3, 2, 0, 0); 433 // tzb differs from tza 434 SimpleTimeZone tzb = new SimpleTimeZone(0, "b", 0, 1, 0, 0, 3, 1, 0, 0); 435 if (tz1.useDaylightTime() || tz2.useDaylightTime() || 436 !tza.useDaylightTime() || !tzA.useDaylightTime() || 437 !tzb.useDaylightTime()) { 438 errln("Test is broken -- rewrite it"); 439 } 440 if (!tza.hasSameRules(tzA) || tza.hasSameRules(tzb)) { 441 errln("Fail: hasSameRules() broken for zones with rules"); 442 } 443 if (!tz1.hasSameRules(tz2)) { 444 errln("Fail: hasSameRules() returns false for zones without rules"); 445 errln("zone 1 = " + tz1); 446 errln("zone 2 = " + tz2); 447 } 448 } 449 450 /** 451 * SimpleTimeZone constructors, setStartRule(), and setEndRule() don't 452 * check for out-of-range arguments. 453 */ Test4154542()454 public void Test4154542() { 455 final int GOOD = 1; 456 final int BAD = 0; 457 458 final int GOOD_MONTH = Calendar.JANUARY; 459 final int GOOD_DAY = 1; 460 final int GOOD_DAY_OF_WEEK = Calendar.SUNDAY; 461 final int GOOD_TIME = 0; 462 463 int[] DATA = { 464 GOOD, Integer.MIN_VALUE, 0, Integer.MAX_VALUE, Integer.MIN_VALUE, 465 GOOD, Calendar.JANUARY, -5, Calendar.SUNDAY, 0, 466 GOOD, Calendar.DECEMBER, 5, Calendar.SATURDAY, 24*60*60*1000-1, 467 GOOD, Calendar.DECEMBER, 5, Calendar.SATURDAY, 24*60*60*1000, 468 BAD, Calendar.DECEMBER, 5, Calendar.SATURDAY, 24*60*60*1000+1, 469 BAD, Calendar.DECEMBER, 5, Calendar.SATURDAY, -1, 470 BAD, Calendar.JANUARY, -6, Calendar.SUNDAY, 0, 471 BAD, Calendar.DECEMBER, 6, Calendar.SATURDAY, 24*60*60*1000, 472 GOOD, Calendar.DECEMBER, 1, 0, 0, 473 GOOD, Calendar.DECEMBER, 31, 0, 0, 474 BAD, Calendar.APRIL, 31, 0, 0, 475 BAD, Calendar.DECEMBER, 32, 0, 0, 476 BAD, Calendar.JANUARY-1, 1, Calendar.SUNDAY, 0, 477 BAD, Calendar.DECEMBER+1, 1, Calendar.SUNDAY, 0, 478 GOOD, Calendar.DECEMBER, 31, -Calendar.SUNDAY, 0, 479 GOOD, Calendar.DECEMBER, 31, -Calendar.SATURDAY, 0, 480 BAD, Calendar.DECEMBER, 32, -Calendar.SATURDAY, 0, 481 BAD, Calendar.DECEMBER, -32, -Calendar.SATURDAY, 0, 482 BAD, Calendar.DECEMBER, 31, -Calendar.SATURDAY-1, 0, 483 }; 484 SimpleTimeZone zone = new SimpleTimeZone(0, "Z"); 485 for (int i=0; i<DATA.length; i+=5) { 486 boolean shouldBeGood = (DATA[i] == GOOD); 487 int month = DATA[i+1]; 488 int day = DATA[i+2]; 489 int dayOfWeek = DATA[i+3]; 490 int time = DATA[i+4]; 491 492 Exception ex = null; 493 try { 494 zone.setStartRule(month, day, dayOfWeek, time); 495 } catch (IllegalArgumentException e) { 496 ex = e; 497 } 498 if ((ex == null) != shouldBeGood) { 499 errln("setStartRule(month=" + month + ", day=" + day + 500 ", dayOfWeek=" + dayOfWeek + ", time=" + time + 501 (shouldBeGood ? (") should work but throws " + ex) 502 : ") should fail but doesn't")); 503 } 504 505 ex = null; 506 try { 507 zone.setEndRule(month, day, dayOfWeek, time); 508 } catch (IllegalArgumentException e) { 509 ex = e; 510 } 511 if ((ex == null) != shouldBeGood) { 512 errln("setEndRule(month=" + month + ", day=" + day + 513 ", dayOfWeek=" + dayOfWeek + ", time=" + time + 514 (shouldBeGood ? (") should work but throws " + ex) 515 : ") should fail but doesn't")); 516 } 517 518 ex = null; 519 try { 520 SimpleTimeZone temp = new SimpleTimeZone(0, "Z", 521 month, day, dayOfWeek, time, 522 GOOD_MONTH, GOOD_DAY, GOOD_DAY_OF_WEEK, GOOD_TIME); 523 } catch (IllegalArgumentException e) { 524 ex = e; 525 } 526 if ((ex == null) != shouldBeGood) { 527 errln("SimpleTimeZone(month=" + month + ", day=" + day + 528 ", dayOfWeek=" + dayOfWeek + ", time=" + time + 529 (shouldBeGood ? (", <end>) should work but throws " + ex) 530 : ", <end>) should fail but doesn't")); 531 } 532 533 ex = null; 534 try { 535 SimpleTimeZone temp = new SimpleTimeZone(0, "Z", 536 GOOD_MONTH, GOOD_DAY, GOOD_DAY_OF_WEEK, GOOD_TIME, 537 month, day, dayOfWeek, time); 538 } catch (IllegalArgumentException e) { 539 ex = e; 540 } 541 if ((ex == null) != shouldBeGood) { 542 errln("SimpleTimeZone(<start>, month=" + month + ", day=" + day + 543 ", dayOfWeek=" + dayOfWeek + ", time=" + time + 544 (shouldBeGood ? (") should work but throws " + ex) 545 : ") should fail but doesn't")); 546 } 547 } 548 } 549 550 /** 551 * SimpleTimeZone.getOffset accepts illegal arguments. 552 */ Test4154650()553 public void Test4154650() { 554 final int GOOD=1, BAD=0; 555 final int GOOD_ERA=GregorianCalendar.AD, GOOD_YEAR=1998, GOOD_MONTH=Calendar.AUGUST; 556 final int GOOD_DAY=2, GOOD_DOW=Calendar.SUNDAY, GOOD_TIME=16*3600000; 557 int[] DATA = { 558 GOOD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, GOOD_TIME, 559 560 GOOD, GregorianCalendar.BC, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, GOOD_TIME, 561 GOOD, GregorianCalendar.AD, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, GOOD_TIME, 562 BAD, GregorianCalendar.BC-1, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, GOOD_TIME, 563 BAD, GregorianCalendar.AD+1, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, GOOD_TIME, 564 565 GOOD, GOOD_ERA, GOOD_YEAR, Calendar.JANUARY, GOOD_DAY, GOOD_DOW, GOOD_TIME, 566 GOOD, GOOD_ERA, GOOD_YEAR, Calendar.DECEMBER, GOOD_DAY, GOOD_DOW, GOOD_TIME, 567 BAD, GOOD_ERA, GOOD_YEAR, Calendar.JANUARY-1, GOOD_DAY, GOOD_DOW, GOOD_TIME, 568 BAD, GOOD_ERA, GOOD_YEAR, Calendar.DECEMBER+1, GOOD_DAY, GOOD_DOW, GOOD_TIME, 569 570 GOOD, GOOD_ERA, GOOD_YEAR, Calendar.JANUARY, 1, GOOD_DOW, GOOD_TIME, 571 GOOD, GOOD_ERA, GOOD_YEAR, Calendar.JANUARY, 31, GOOD_DOW, GOOD_TIME, 572 BAD, GOOD_ERA, GOOD_YEAR, Calendar.JANUARY, 0, GOOD_DOW, GOOD_TIME, 573 BAD, GOOD_ERA, GOOD_YEAR, Calendar.JANUARY, 32, GOOD_DOW, GOOD_TIME, 574 575 GOOD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, Calendar.SUNDAY, GOOD_TIME, 576 GOOD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, Calendar.SATURDAY, GOOD_TIME, 577 BAD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, Calendar.SUNDAY-1, GOOD_TIME, 578 BAD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, Calendar.SATURDAY+1, GOOD_TIME, 579 580 GOOD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, 0, 581 GOOD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, 24*3600000-1, 582 BAD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, -1, 583 BAD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, 24*3600000, 584 }; 585 586 TimeZone tz = TimeZone.getDefault(); 587 for (int i=0; i<DATA.length; i+=7) { 588 boolean good = DATA[i] == GOOD; 589 IllegalArgumentException e = null; 590 try { 591 int offset = tz.getOffset(DATA[i+1], DATA[i+2], DATA[i+3], 592 DATA[i+4], DATA[i+5], DATA[i+6]); 593 } catch (IllegalArgumentException ex) { 594 e = ex; 595 } 596 if (good != (e == null)) { 597 errln("Fail: getOffset(" + 598 DATA[i+1] + ", " + DATA[i+2] + ", " + DATA[i+3] + ", " + 599 DATA[i+4] + ", " + DATA[i+5] + ", " + DATA[i+6] + 600 (good ? (") threw " + e) : ") accepts invalid args")); 601 } 602 } 603 } 604 605 /** 606 * TimeZone constructors allow null IDs. 607 */ Test4159922()608 public void Test4159922() { 609 TimeZone z = null; 610 611 // TimeZone API. Only hasSameRules() and setDefault() should 612 // allow null. 613 try { 614 z = TimeZone.getTimeZone((String)null); 615 errln("FAIL: Null allowed in getTimeZone"); 616 } catch (NullPointerException e) {} 617 z = TimeZone.getTimeZone("GMT"); 618 try { 619 z.getDisplayName(false, TimeZone.SHORT, null); 620 errln("FAIL: Null allowed in getDisplayName(3)"); 621 } catch (NullPointerException e) {} 622 try { 623 z.getDisplayName(null); 624 errln("FAIL: Null allowed in getDisplayName(1)"); 625 } catch (NullPointerException e) {} 626 try { 627 if (z.hasSameRules(null)) { 628 errln("FAIL: hasSameRules returned true"); 629 } 630 } catch (NullPointerException e) { 631 errln("FAIL: Null NOT allowed in hasSameRules"); 632 } 633 try { 634 z.inDaylightTime(null); 635 errln("FAIL: Null allowed in inDaylightTime"); 636 } catch (NullPointerException e) {} 637 try { 638 z.setID(null); 639 errln("FAIL: Null allowed in setID"); 640 } catch (NullPointerException e) {} 641 642 TimeZone save = TimeZone.getDefault(); 643 try { 644 TimeZone.setDefault(null); 645 } catch (NullPointerException e) { 646 errln("FAIL: Null NOT allowed in setDefault"); 647 } finally { 648 TimeZone.setDefault(save); 649 } 650 651 // SimpleTimeZone API 652 SimpleTimeZone s = null; 653 try { 654 s = new SimpleTimeZone(0, null); 655 errln("FAIL: Null allowed in SimpleTimeZone(2)"); 656 } catch (NullPointerException e) {} 657 try { 658 s = new SimpleTimeZone(0, null, 0, 1, 0, 0, 0, 1, 0, 0); 659 errln("FAIL: Null allowed in SimpleTimeZone(10)"); 660 } catch (NullPointerException e) {} 661 try { 662 s = new SimpleTimeZone(0, null, 0, 1, 0, 0, 0, 1, 0, 0, 1000); 663 errln("FAIL: Null allowed in SimpleTimeZone(11)"); 664 } catch (NullPointerException e) {} 665 } 666 667 /** 668 * TimeZone broken at midnight. The TimeZone code fails to handle 669 * transitions at midnight correctly. 670 */ 671 @SuppressWarnings("deprecation") Test4162593()672 public void Test4162593() { 673 SimpleDateFormat fmt = new SimpleDateFormat("z", Locale.US); 674 final int ONE_HOUR = 60*60*1000; 675 TimeZone initialZone = TimeZone.getDefault(); 676 677 SimpleTimeZone asuncion = new SimpleTimeZone(-4*ONE_HOUR, "America/Asuncion" /*PY%sT*/, 678 Calendar.OCTOBER, 1, 0 /*DOM*/, 0*ONE_HOUR, 679 Calendar.MARCH, 1, 0 /*DOM*/, 0*ONE_HOUR, 1*ONE_HOUR); 680 681 /* Zone 682 * Starting time 683 * Transition expected between start+1H and start+2H 684 */ 685 Object[] DATA = { 686 new SimpleTimeZone(2*ONE_HOUR, "Asia/Damascus" /*EE%sT*/, 687 Calendar.APRIL, 1, 0 /*DOM*/, 0*ONE_HOUR, 688 Calendar.OCTOBER, 1, 0 /*DOM*/, 0*ONE_HOUR, 1*ONE_HOUR), 689 new int[] {98, Calendar.SEPTEMBER, 30, 22, 0}, 690 Boolean.TRUE, 691 692 asuncion, 693 new int[] {100, Calendar.FEBRUARY, 28, 22, 0}, 694 Boolean.FALSE, 695 696 asuncion, 697 new int[] {100, Calendar.FEBRUARY, 29, 22, 0}, 698 Boolean.TRUE, 699 }; 700 701 String[] zone = new String[4]; 702 703 try { 704 for (int j=0; j<DATA.length; j+=3) { 705 TimeZone tz = (TimeZone)DATA[j]; 706 TimeZone.setDefault(tz); 707 fmt.setTimeZone(tz); 708 709 // Must construct the Date object AFTER setting the default zone 710 int[] p = (int[])DATA[j+1]; 711 Date d = new Date(p[0], p[1], p[2], p[3], p[4]); 712 boolean transitionExpected = ((Boolean)DATA[j+2]).booleanValue(); 713 714 logln(tz.getID() + ":"); 715 for (int i=0; i<4; ++i) { 716 zone[i] = fmt.format(d); 717 logln("" + i + ": " + d); 718 d = new Date(d.getTime() + ONE_HOUR); 719 } 720 if (zone[0].equals(zone[1]) && 721 (zone[1].equals(zone[2]) != transitionExpected) && 722 zone[2].equals(zone[3])) { 723 logln("Ok: transition " + transitionExpected); 724 } else { 725 errln("Fail: boundary transition incorrect"); 726 } 727 } 728 } 729 finally { 730 // restore the initial time zone so that this test case 731 // doesn't affect the others. 732 TimeZone.setDefault(initialZone); 733 } 734 } 735 736 /** 737 * TimeZone broken in last hour of year 738 */ Test4173604()739 public void Test4173604() { 740 // test both SimpleTimeZone and ZoneInfo objects. 741 // @since 1.4 742 sub4173604(getPST()); 743 sub4173604(TimeZone.getTimeZone("PST")); 744 } 745 sub4173604(TimeZone pst)746 private void sub4173604(TimeZone pst) { 747 int o22 = pst.getOffset(1, 1998, 11, 31, Calendar.THURSDAY, 22*60*60*1000); 748 int o23 = pst.getOffset(1, 1998, 11, 31, Calendar.THURSDAY, 23*60*60*1000); 749 int o00 = pst.getOffset(1, 1999, 0, 1, Calendar.FRIDAY, 0); 750 if (o22 != o23 || o22 != o00) { 751 errln("Offsets should be the same (for PST), but got: " + 752 "12/31 22:00 " + o22 + 753 ", 12/31 23:00 " + o23 + 754 ", 01/01 00:00 " + o00); 755 } 756 757 GregorianCalendar cal = new GregorianCalendar(); 758 cal.setTimeZone(pst); 759 cal.clear(); 760 cal.set(1998, Calendar.JANUARY, 1); 761 int lastDST = cal.get(Calendar.DST_OFFSET); 762 int transitions = 0; 763 int delta = 5; 764 while (cal.get(Calendar.YEAR) < 2000) { 765 cal.add(Calendar.MINUTE, delta); 766 if (cal.get(Calendar.DST_OFFSET) != lastDST) { 767 ++transitions; 768 Calendar t = (Calendar)cal.clone(); 769 t.add(Calendar.MINUTE, -delta); 770 logln(t.getTime() + " " + t.get(Calendar.DST_OFFSET)); 771 logln(cal.getTime() + " " + (lastDST=cal.get(Calendar.DST_OFFSET))); 772 } 773 } 774 if (transitions != 4) { 775 errln("Saw " + transitions + " transitions; should have seen 4"); 776 } 777 } 778 779 /** 780 * getDisplayName doesn't work with unusual savings/offsets. 781 */ 782 @SuppressWarnings("deprecation") Test4176686()783 public void Test4176686() { 784 // Construct a zone that does not observe DST but 785 // that does have a DST savings (which should be ignored). 786 int offset = 90 * 60000; // 1:30 787 SimpleTimeZone z1 = new SimpleTimeZone(offset, "_std_zone_"); 788 z1.setDSTSavings(45 * 60000); // 0:45 789 790 // Construct a zone that observes DST for the first 6 months. 791 SimpleTimeZone z2 = new SimpleTimeZone(offset, "_dst_zone_"); 792 z2.setDSTSavings(45 * 60000); // 0:45 793 z2.setStartRule(Calendar.JANUARY, 1, 0); 794 z2.setEndRule(Calendar.JULY, 1, 0); 795 796 // Also check DateFormat 797 DateFormat fmt1 = new SimpleDateFormat("z"); 798 fmt1.setTimeZone(z1); // Format uses standard zone 799 DateFormat fmt2 = new SimpleDateFormat("z"); 800 fmt2.setTimeZone(z2); // Format uses DST zone 801 Date dst = new Date(1970-1900, Calendar.FEBRUARY, 1); // Time in DST 802 Date std = new Date(1970-1900, Calendar.AUGUST, 1); // Time in standard 803 804 // Description, Result, Expected Result 805 String[] DATA = { 806 "getDisplayName(false, SHORT)/std zone", 807 z1.getDisplayName(false, TimeZone.SHORT), "GMT+01:30", 808 "getDisplayName(false, LONG)/std zone", 809 z1.getDisplayName(false, TimeZone.LONG ), "GMT+01:30", 810 "getDisplayName(true, SHORT)/std zone", 811 z1.getDisplayName(true, TimeZone.SHORT), "GMT+01:30", 812 "getDisplayName(true, LONG)/std zone", 813 z1.getDisplayName(true, TimeZone.LONG ), "GMT+01:30", 814 "getDisplayName(false, SHORT)/dst zone", 815 z2.getDisplayName(false, TimeZone.SHORT), "GMT+01:30", 816 "getDisplayName(false, LONG)/dst zone", 817 z2.getDisplayName(false, TimeZone.LONG ), "GMT+01:30", 818 "getDisplayName(true, SHORT)/dst zone", 819 z2.getDisplayName(true, TimeZone.SHORT), "GMT+02:15", 820 "getDisplayName(true, LONG)/dst zone", 821 z2.getDisplayName(true, TimeZone.LONG ), "GMT+02:15", 822 "DateFormat.format(std)/std zone", fmt1.format(std), "GMT+01:30", 823 "DateFormat.format(dst)/std zone", fmt1.format(dst), "GMT+01:30", 824 "DateFormat.format(std)/dst zone", fmt2.format(std), "GMT+01:30", 825 "DateFormat.format(dst)/dst zone", fmt2.format(dst), "GMT+02:15", 826 }; 827 828 for (int i=0; i<DATA.length; i+=3) { 829 if (!DATA[i+1].equals(DATA[i+2])) { 830 errln("FAIL: " + DATA[i] + " -> " + DATA[i+1] + ", exp " + DATA[i+2]); 831 } 832 } 833 } 834 835 /** 836 * SimpleTimeZone allows invalid DOM values. 837 */ Test4184229()838 public void Test4184229() { 839 SimpleTimeZone zone = null; 840 try { 841 zone = new SimpleTimeZone(0, "A", 0, -1, 0, 0, 0, 0, 0, 0); 842 errln("Failed. No exception has been thrown for DOM -1 startDay"); 843 } catch(IllegalArgumentException e) { 844 logln("(a) " + e.getMessage()); 845 } 846 try { 847 zone = new SimpleTimeZone(0, "A", 0, 0, 0, 0, 0, -1, 0, 0); 848 errln("Failed. No exception has been thrown for DOM -1 endDay"); 849 } catch(IllegalArgumentException e) { 850 logln("(b) " + e.getMessage()); 851 } 852 try { 853 zone = new SimpleTimeZone(0, "A", 0, -1, 0, 0, 0, 0, 0, 0, 1000); 854 errln("Failed. No exception has been thrown for DOM -1 startDay +savings"); 855 } catch(IllegalArgumentException e) { 856 logln("(c) " + e.getMessage()); 857 } 858 try { 859 zone = new SimpleTimeZone(0, "A", 0, 0, 0, 0, 0, -1, 0, 0, 1000); 860 errln("Failed. No exception has been thrown for DOM -1 endDay +savings"); 861 } catch(IllegalArgumentException e) { 862 logln("(d) " + e.getMessage()); 863 } 864 // Make a valid constructor call for subsequent tests. 865 zone = new SimpleTimeZone(0, "A", 0, 1, 0, 0, 0, 1, 0, 0); 866 try { 867 zone.setStartRule(0, -1, 0, 0); 868 errln("Failed. No exception has been thrown for DOM -1 setStartRule +savings"); 869 } catch(IllegalArgumentException e) { 870 logln("(e) " + e.getMessage()); 871 } 872 try { 873 zone.setStartRule(0, -1, 0); 874 errln("Failed. No exception has been thrown for DOM -1 setStartRule"); 875 } catch(IllegalArgumentException e) { 876 logln("(f) " + e.getMessage()); 877 } 878 try { 879 zone.setEndRule(0, -1, 0, 0); 880 errln("Failed. No exception has been thrown for DOM -1 setEndRule +savings"); 881 } catch(IllegalArgumentException e) { 882 logln("(g) " + e.getMessage()); 883 } 884 try { 885 zone.setEndRule(0, -1, 0); 886 errln("Failed. No exception has been thrown for DOM -1 setEndRule"); 887 } catch(IllegalArgumentException e) { 888 logln("(h) " + e.getMessage()); 889 } 890 } 891 892 /** 893 * SimpleTimeZone.getOffset() throws IllegalArgumentException when to get 894 * of 2/29/1996 (leap day). 895 */ Test4208960()896 public void Test4208960 () { 897 // test both SimpleTimeZone and ZoneInfo objects. 898 // @since 1.4 899 sub4208960(getPST()); 900 sub4208960(TimeZone.getTimeZone("PST")); 901 } 902 sub4208960(TimeZone tz)903 private void sub4208960(TimeZone tz) { 904 try { 905 int offset = tz.getOffset(GregorianCalendar.AD, 1996, Calendar.FEBRUARY, 29, 906 Calendar.THURSDAY, 0); 907 } catch (IllegalArgumentException e) { 908 errln("FAILED: to get TimeZone.getOffset(2/29/96)"); 909 } 910 try { 911 int offset = tz.getOffset(GregorianCalendar.AD, 1997, Calendar.FEBRUARY, 29, 912 Calendar.THURSDAY, 0); 913 errln("FAILED: TimeZone.getOffset(2/29/97) expected to throw Exception."); 914 } catch (IllegalArgumentException e) { 915 logln("got IllegalArgumentException"); 916 } 917 } 918 919 /** 920 * 4966229: java.util.Date methods may works incorrect. 921 * sun.util.calendar.ZoneInfo doesn't clone properly. 922 */ 923 @SuppressWarnings("deprecation") Test4966229()924 public void Test4966229() { 925 TimeZone savedTZ = TimeZone.getDefault(); 926 try { 927 TimeZone.setDefault(TimeZone.getTimeZone("GMT")); 928 Date d = new Date(2100-1900, 5, 1); // specify year >2037 929 TimeZone tz = TimeZone.getTimeZone("America/Los_Angeles"); 930 931 Calendar cal = new GregorianCalendar(tz); 932 cal.setTime(d); 933 934 // Change the raw offset in tz 935 int offset = tz.getRawOffset(); 936 tz.setRawOffset(0); 937 938 TimeZone tz2 = (TimeZone) tz.clone(); 939 Calendar cal2 = new GregorianCalendar(tz2); 940 cal2.setTime(d); 941 int expectedHourOfDay = cal2.get(cal.HOUR_OF_DAY); 942 943 // Restore the GMT offset in tz which shouldn't affect tz2 944 tz.setRawOffset(offset); 945 cal2.setTime(d); 946 int hourOfDay = cal2.get(cal.HOUR_OF_DAY); 947 if (hourOfDay != expectedHourOfDay) { 948 errln("wrong hour of day: got: " + hourOfDay 949 + ", expected: " + expectedHourOfDay); 950 } 951 } finally { 952 TimeZone.setDefault(savedTZ); 953 } 954 } 955 956 /** 957 * 6433179: (tz) Incorrect DST end for America/Winnipeg and Canada/Central in 2038+ 958 */ Test6433179()959 public void Test6433179() { 960 // Use the old America/Winnipeg rule for testing. Note that 961 // startMode is WALL_TIME for testing. It's actually 962 // STANDARD_TIME, though. 963 //Rule Winn 1966 2005 - Oct lastSun 2:00s 0 S 964 //Rule Winn 1987 2005 - Apr Sun>=1 2:00s 1:00 D 965 TimeZone tz = new SimpleTimeZone(-6*ONE_HOUR, "America/Winnipeg", 966 Calendar.APRIL, 1, -Calendar.SUNDAY, 2*ONE_HOUR, SimpleTimeZone.WALL_TIME, 967 Calendar.OCTOBER, -1, Calendar.SUNDAY, 2*ONE_HOUR, SimpleTimeZone.STANDARD_TIME, 968 1*ONE_HOUR); 969 Calendar cal = Calendar.getInstance(tz, Locale.US); 970 cal.clear(); 971 cal.set(2039, Calendar.OCTOBER, 1); 972 cal.getTime(); 973 cal.set(cal.DAY_OF_WEEK, cal.SUNDAY); 974 cal.set(cal.DAY_OF_WEEK_IN_MONTH, -1); 975 cal.add(Calendar.HOUR_OF_DAY, 2); 976 if (cal.get(cal.DST_OFFSET) == 0) { 977 errln("Should still be in DST."); 978 } 979 } 980 981 private static final int ONE_HOUR = 60 * 60 * 1000; 982 /** 983 * Returns an instance of SimpleTimeZone for 984 * "PST". (TimeZone.getTimeZone() no longer returns a 985 * SimpleTimeZone object.) 986 * @since 1.4 987 */ getPST()988 private SimpleTimeZone getPST() { 989 return new SimpleTimeZone(-8*ONE_HOUR, "PST", 990 Calendar.APRIL, 1, -Calendar.SUNDAY, 2*ONE_HOUR, 991 Calendar.OCTOBER, -1, Calendar.SUNDAY, 2*ONE_HOUR, 992 1*ONE_HOUR); 993 } 994 } 995 //eof 996