1 /* 2 * Copyright (c) 1997, 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 4028006 4044013 4096694 4107276 4107570 4112869 4130885 7039469 7126465 7158483 27 * 8008577 8077685 8098547 8133321 8138716 8148446 8151876 8159684 8166875 28 * @modules java.base/sun.util.resources 29 * @library /java/text/testlib 30 * @summary test TimeZone 31 */ 32 33 import java.io.*; 34 import java.text.*; 35 import java.util.*; 36 import sun.util.resources.LocaleData; 37 38 public class TimeZoneTest extends IntlTest 39 { 40 static final int millisPerHour = 3600000; 41 42 public static void main(String[] args) throws Exception { 43 new TimeZoneTest().run(args); 44 } 45 46 /** 47 * Bug 4130885 48 * Certain short zone IDs, used since 1.1.x, are incorrect. 49 * 50 * The worst of these is: 51 * 52 * "CAT" (Central African Time) should be GMT+2:00, but instead returns a 53 * zone at GMT-1:00. The zone at GMT-1:00 should be called EGT, CVT, EGST, 54 * or AZOST, depending on which zone is meant, but in no case is it CAT. 55 * 56 * Other wrong zone IDs: 57 * 58 * ECT (European Central Time) GMT+1:00: ECT is Ecuador Time, 59 * GMT-5:00. European Central time is abbreviated CEST. 60 * 61 * SST (Solomon Island Time) GMT+11:00. SST is actually Samoa Standard Time, 62 * GMT-11:00. Solomon Island time is SBT. 63 * 64 * NST (New Zealand Time) GMT+12:00. NST is the abbreviation for 65 * Newfoundland Standard Time, GMT-3:30. New Zealanders use NZST. 66 * 67 * AST (Alaska Standard Time) GMT-9:00. [This has already been noted in 68 * another bug.] It should be "AKST". AST is Atlantic Standard Time, 69 * GMT-4:00. 70 * 71 * PNT (Phoenix Time) GMT-7:00. PNT usually means Pitcairn Time, 72 * GMT-8:30. There is no standard abbreviation for Phoenix time, as distinct 73 * from MST with daylight savings. 74 * 75 * In addition to these problems, a number of zones are FAKE. That is, they 76 * don't match what people use in the real world. 77 * 78 * FAKE zones: 79 * 80 * EET (should be EEST) 81 * ART (should be EET) 82 * MET (should be IRST) 83 * NET (should be AMST) 84 * PLT (should be PKT) 85 * BST (should be BDT) 86 * VST (should be ICT) 87 * CTT (should be CST) + 88 * ACT (should be CST) + 89 * AET (should be EST) + 90 * MIT (should be WST) + 91 * IET (should be EST) + 92 * PRT (should be AST) + 93 * CNT (should be NST) 94 * AGT (should be ARST) 95 * BET (should be EST) + 96 * 97 * + A zone with the correct name already exists and means something 98 * else. E.g., EST usually indicates the US Eastern zone, so it cannot be 99 * used for Brazil (BET). 100 */ 101 public void TestShortZoneIDs() throws Exception { 102 103 ZoneDescriptor[] JDK_116_REFERENCE_LIST = { 104 new ZoneDescriptor("MIT", 780, true), 105 new ZoneDescriptor("HST", -600, false), 106 new ZoneDescriptor("AST", -540, true), 107 new ZoneDescriptor("PST", -480, true), 108 new ZoneDescriptor("PNT", -420, false), 109 new ZoneDescriptor("MST", -420, false), 110 new ZoneDescriptor("CST", -360, true), 111 new ZoneDescriptor("IET", -300, true), 112 new ZoneDescriptor("EST", -300, false), 113 new ZoneDescriptor("PRT", -240, false), 114 new ZoneDescriptor("CNT", -210, true), 115 new ZoneDescriptor("AGT", -180, false), 116 new ZoneDescriptor("BET", -180, true), 117 // new ZoneDescriptor("CAT", -60, false), // Wrong: 118 // As of bug 4130885, fix CAT (Central Africa) 119 new ZoneDescriptor("CAT", 120, false), // Africa/Harare 120 new ZoneDescriptor("GMT", 0, false), 121 new ZoneDescriptor("UTC", 0, false), 122 new ZoneDescriptor("ECT", 60, true), 123 new ZoneDescriptor("ART", 120, false), 124 new ZoneDescriptor("EET", 120, true), 125 new ZoneDescriptor("EAT", 180, false), 126 new ZoneDescriptor("MET", 60, true), 127 new ZoneDescriptor("NET", 240, false), 128 new ZoneDescriptor("PLT", 300, false), 129 new ZoneDescriptor("IST", 330, false), 130 new ZoneDescriptor("BST", 360, false), 131 new ZoneDescriptor("VST", 420, false), 132 new ZoneDescriptor("CTT", 480, false), 133 new ZoneDescriptor("JST", 540, false), 134 new ZoneDescriptor("ACT", 570, false), 135 new ZoneDescriptor("AET", 600, true), 136 new ZoneDescriptor("SST", 660, false), 137 // new ZoneDescriptor("NST", 720, false), 138 // As of bug 4130885, fix NST (New Zealand) 139 new ZoneDescriptor("NST", 720, true), // Pacific/Auckland 140 }; 141 142 Map<String, ZoneDescriptor> hash = new HashMap<>(); 143 144 String[] ids = TimeZone.getAvailableIDs(); 145 for (String id : ids) { 146 if (id.length() == 3) { 147 hash.put(id, new ZoneDescriptor(TimeZone.getTimeZone(id))); 148 } 149 } 150 151 for (int i = 0; i < JDK_116_REFERENCE_LIST.length; ++i) { 152 ZoneDescriptor referenceZone = JDK_116_REFERENCE_LIST[i]; 153 ZoneDescriptor currentZone = hash.get(referenceZone.getID()); 154 if (referenceZone.equals(currentZone)) { 155 logln("ok " + referenceZone); 156 } 157 else { 158 errln("Fail: Expected " + referenceZone + 159 "; got " + currentZone); 160 } 161 } 162 } 163 164 /** 165 * A descriptor for a zone; used to regress the short zone IDs. 166 */ 167 static class ZoneDescriptor { 168 String id; 169 int offset; // In minutes 170 boolean daylight; 171 172 ZoneDescriptor(TimeZone zone) { 173 this.id = zone.getID(); 174 this.offset = zone.getRawOffset() / 60000; 175 this.daylight = zone.useDaylightTime(); 176 } 177 178 ZoneDescriptor(String id, int offset, boolean daylight) { 179 this.id = id; 180 this.offset = offset; 181 this.daylight = daylight; 182 } 183 184 public String getID() { return id; } 185 186 @Override 187 public boolean equals(Object o) { 188 ZoneDescriptor that = (ZoneDescriptor)o; 189 return that != null && 190 id.equals(that.id) && 191 offset == that.offset && 192 daylight == that.daylight; 193 } 194 195 @Override 196 public int hashCode() { 197 return id.hashCode() ^ offset | (daylight ? 1 : 0); 198 } 199 200 @Override 201 public String toString() { 202 int min = offset; 203 char sign = '+'; 204 if (min < 0) { sign = '-'; min = -min; } 205 206 return "Zone[\"" + id + "\", GMT" + sign + (min/60) + ':' + 207 (min%60<10?"0":"") + (min%60) + ", " + 208 (daylight ? "Daylight" : "Standard") + "]"; 209 } 210 211 public static int compare(Object o1, Object o2) { 212 ZoneDescriptor i1 = (ZoneDescriptor)o1; 213 ZoneDescriptor i2 = (ZoneDescriptor)o2; 214 if (i1.offset > i2.offset) return 1; 215 if (i1.offset < i2.offset) return -1; 216 if (i1.daylight && !i2.daylight) return 1; 217 if (!i1.daylight && i2.daylight) return -1; 218 return i1.id.compareTo(i2.id); 219 } 220 } 221 222 static final String formatMinutes(int min) { 223 char sign = '+'; 224 if (min < 0) { sign = '-'; min = -min; } 225 int h = min/60; 226 min = min%60; 227 return "" + sign + h + ":" + ((min<10) ? "0" : "") + min; 228 } 229 /** 230 * As part of the VM fix (see CCC approved RFE 4028006, bug 231 * 4044013), TimeZone.getTimeZone() has been modified to recognize 232 * generic IDs of the form GMT[+-]hh:mm, GMT[+-]hhmm, and 233 * GMT[+-]hh. Test this behavior here. 234 * 235 * Bug 4044013 236 * 237 * ID "Custom" is no longer used for TimeZone objects created with 238 * a custom time zone ID, such as "GMT-8". See 4322313. 239 */ 240 public void TestCustomParse() throws Exception { 241 Object[] DATA = { 242 // ID Expected offset in minutes 243 "GMT", null, 244 "GMT+0", new Integer(0), 245 "GMT+1", new Integer(60), 246 "GMT-0030", new Integer(-30), 247 "GMT+15:99", null, 248 "GMT+", null, 249 "GMT-", null, 250 "GMT+0:", null, 251 "GMT-:", null, 252 "GMT+0010", new Integer(10), // Interpret this as 00:10 253 "GMT-10", new Integer(-10*60), 254 "GMT+30", null, 255 "GMT-3:30", new Integer(-(3*60+30)), 256 "GMT-230", new Integer(-(2*60+30)), 257 }; 258 for (int i=0; i<DATA.length; i+=2) { 259 String id = (String)DATA[i]; 260 Integer exp = (Integer)DATA[i+1]; 261 TimeZone zone = TimeZone.getTimeZone(id); 262 if (zone.getID().equals("GMT")) { 263 logln(id + " -> generic GMT"); 264 // When TimeZone.getTimeZone() can't parse the id, it 265 // returns GMT -- a dubious practice, but required for 266 // backward compatibility. 267 if (exp != null) { 268 throw new Exception("Expected offset of " + formatMinutes(exp.intValue()) + 269 " for " + id + ", got parse failure"); 270 } 271 } 272 else { 273 int ioffset = zone.getRawOffset()/60000; 274 String offset = formatMinutes(ioffset); 275 logln(id + " -> " + zone.getID() + " GMT" + offset); 276 if (exp == null) { 277 throw new Exception("Expected parse failure for " + id + 278 ", got offset of " + offset + 279 ", id " + zone.getID()); 280 } 281 else if (ioffset != exp.intValue()) { 282 throw new Exception("Expected offset of " + formatMinutes(exp.intValue()) + 283 ", id Custom, for " + id + 284 ", got offset of " + offset + 285 ", id " + zone.getID()); 286 } 287 } 288 } 289 } 290 291 /** 292 * Test the basic functionality of the getDisplayName() API. 293 * 294 * Bug 4112869 295 * Bug 4028006 296 * 297 * See also API change request A41. 298 * 299 * 4/21/98 - make smarter, so the test works if the ext resources 300 * are present or not. 301 */ 302 public void TestDisplayName() { 303 TimeZone zone = TimeZone.getTimeZone("PST"); 304 String name = zone.getDisplayName(Locale.ENGLISH); 305 logln("PST->" + name); 306 if (!name.equals("Pacific Standard Time")) 307 errln("Fail: Expected \"Pacific Standard Time\""); 308 309 //***************************************************************** 310 // THE FOLLOWING LINES MUST BE UPDATED IF THE LOCALE DATA CHANGES 311 // THE FOLLOWING LINES MUST BE UPDATED IF THE LOCALE DATA CHANGES 312 // THE FOLLOWING LINES MUST BE UPDATED IF THE LOCALE DATA CHANGES 313 //***************************************************************** 314 Object[] DATA = { 315 new Boolean(false), new Integer(TimeZone.SHORT), "PST", 316 new Boolean(true), new Integer(TimeZone.SHORT), "PDT", 317 new Boolean(false), new Integer(TimeZone.LONG), "Pacific Standard Time", 318 new Boolean(true), new Integer(TimeZone.LONG), "Pacific Daylight Time", 319 }; 320 321 for (int i=0; i<DATA.length; i+=3) { 322 name = zone.getDisplayName(((Boolean)DATA[i]).booleanValue(), 323 ((Integer)DATA[i+1]).intValue(), 324 Locale.ENGLISH); 325 if (!name.equals(DATA[i+2])) 326 errln("Fail: Expected " + DATA[i+2] + "; got " + name); 327 } 328 329 // Make sure that we don't display the DST name by constructing a fake 330 // PST zone that has DST all year long. 331 SimpleTimeZone zone2 = new SimpleTimeZone(0, "PST"); 332 zone2.setStartRule(Calendar.JANUARY, 1, 0); 333 zone2.setEndRule(Calendar.DECEMBER, 31, 0); 334 logln("Modified PST inDaylightTime->" + zone2.inDaylightTime(new Date())); 335 name = zone2.getDisplayName(Locale.ENGLISH); 336 logln("Modified PST->" + name); 337 if (!name.equals("Pacific Standard Time")) 338 errln("Fail: Expected \"Pacific Standard Time\""); 339 340 // Make sure we get the default display format for Locales 341 // with no display name data. 342 Locale zh_CN = Locale.SIMPLIFIED_CHINESE; 343 name = zone.getDisplayName(zh_CN); 344 //***************************************************************** 345 // THE FOLLOWING LINE MUST BE UPDATED IF THE LOCALE DATA CHANGES 346 // THE FOLLOWING LINE MUST BE UPDATED IF THE LOCALE DATA CHANGES 347 // THE FOLLOWING LINE MUST BE UPDATED IF THE LOCALE DATA CHANGES 348 //***************************************************************** 349 logln("PST(zh_CN)->" + name); 350 351 // Now be smart -- check to see if zh resource is even present. 352 // If not, we expect the en fallback behavior. 353 ResourceBundle enRB = LocaleData.getBundle("sun.util.resources.TimeZoneNames", 354 Locale.ENGLISH); 355 ResourceBundle zhRB = LocaleData.getBundle("sun.util.resources.TimeZoneNames", 356 zh_CN); 357 358 boolean noZH = enRB == zhRB; 359 360 if (noZH) { 361 logln("Warning: Not testing the zh_CN behavior because resource is absent"); 362 if (!name.equals("Pacific Standard Time")) 363 errln("Fail: Expected Pacific Standard Time"); 364 } 365 else if (!name.equals("Pacific Standard Time") && 366 !name.equals("\u592a\u5e73\u6d0b\u6807\u51c6\u65f6\u95f4") && 367 !name.equals("GMT-08:00") && 368 !name.equals("GMT-8:00") && 369 !name.equals("GMT-0800") && 370 !name.equals("GMT-800")) { 371 errln("Fail: Expected GMT-08:00 or something similar"); 372 errln("************************************************************"); 373 errln("THE ABOVE FAILURE MAY JUST MEAN THE LOCALE DATA HAS CHANGED"); 374 errln("************************************************************"); 375 } 376 377 // Now try a non-existent zone 378 zone2 = new SimpleTimeZone(90*60*1000, "xyzzy"); 379 name = zone2.getDisplayName(Locale.ENGLISH); 380 logln("GMT+90min->" + name); 381 if (!name.equals("GMT+01:30") && 382 !name.equals("GMT+1:30") && 383 !name.equals("GMT+0130") && 384 !name.equals("GMT+130")) 385 errln("Fail: Expected GMT+01:30 or something similar"); 386 } 387 388 public void TestGenericAPI() { 389 String id = "NewGMT"; 390 int offset = 12345; 391 392 SimpleTimeZone zone = new SimpleTimeZone(offset, id); 393 if (zone.useDaylightTime()) { 394 errln("FAIL: useDaylightTime should return false"); 395 } 396 397 TimeZone zoneclone = (TimeZone)zone.clone(); 398 if (!zoneclone.equals(zone)) { 399 errln("FAIL: clone or operator== failed"); 400 } 401 zoneclone.setID("abc"); 402 if (zoneclone.equals(zone)) { 403 errln("FAIL: clone or operator!= failed"); 404 } 405 406 zoneclone = (TimeZone)zone.clone(); 407 if (!zoneclone.equals(zone)) { 408 errln("FAIL: clone or operator== failed"); 409 } 410 zoneclone.setRawOffset(45678); 411 if (zoneclone.equals(zone)) { 412 errln("FAIL: clone or operator!= failed"); 413 } 414 415 TimeZone saveDefault = TimeZone.getDefault(); 416 try { 417 TimeZone.setDefault(zone); 418 TimeZone defaultzone = TimeZone.getDefault(); 419 if (defaultzone == zone) { 420 errln("FAIL: Default object is identical, not clone"); 421 } 422 if (!defaultzone.equals(zone)) { 423 errln("FAIL: Default object is not equal"); 424 } 425 } 426 finally { 427 TimeZone.setDefault(saveDefault); 428 } 429 } 430 431 @SuppressWarnings("deprecation") 432 public void TestRuleAPI() 433 { 434 // ErrorCode status = ZERO_ERROR; 435 436 int offset = (int)(60*60*1000*1.75); // Pick a weird offset 437 SimpleTimeZone zone = new SimpleTimeZone(offset, "TestZone"); 438 if (zone.useDaylightTime()) errln("FAIL: useDaylightTime should return false"); 439 440 // Establish our expected transition times. Do this with a non-DST 441 // calendar with the (above) declared local offset. 442 GregorianCalendar gc = new GregorianCalendar(zone); 443 gc.clear(); 444 gc.set(1990, Calendar.MARCH, 1); 445 long marchOneStd = gc.getTime().getTime(); // Local Std time midnight 446 gc.clear(); 447 gc.set(1990, Calendar.JULY, 1); 448 long julyOneStd = gc.getTime().getTime(); // Local Std time midnight 449 450 // Starting and ending hours, WALL TIME 451 int startHour = (int)(2.25 * 3600000); 452 int endHour = (int)(3.5 * 3600000); 453 454 zone.setStartRule(Calendar.MARCH, 1, 0, startHour); 455 zone.setEndRule (Calendar.JULY, 1, 0, endHour); 456 457 gc = new GregorianCalendar(zone); 458 // if (failure(status, "new GregorianCalendar")) return; 459 460 long marchOne = marchOneStd + startHour; 461 long julyOne = julyOneStd + endHour - 3600000; // Adjust from wall to Std time 462 463 long expMarchOne = 636251400000L; 464 if (marchOne != expMarchOne) 465 { 466 errln("FAIL: Expected start computed as " + marchOne + 467 " = " + new Date(marchOne)); 468 logln(" Should be " + expMarchOne + 469 " = " + new Date(expMarchOne)); 470 } 471 472 long expJulyOne = 646793100000L; 473 if (julyOne != expJulyOne) 474 { 475 errln("FAIL: Expected start computed as " + julyOne + 476 " = " + new Date(julyOne)); 477 logln(" Should be " + expJulyOne + 478 " = " + new Date(expJulyOne)); 479 } 480 481 testUsingBinarySearch(zone, new Date(90, Calendar.JANUARY, 1).getTime(), 482 new Date(90, Calendar.JUNE, 15).getTime(), marchOne); 483 testUsingBinarySearch(zone, new Date(90, Calendar.JUNE, 1).getTime(), 484 new Date(90, Calendar.DECEMBER, 31).getTime(), julyOne); 485 486 if (zone.inDaylightTime(new Date(marchOne - 1000)) || 487 !zone.inDaylightTime(new Date(marchOne))) 488 errln("FAIL: Start rule broken"); 489 if (!zone.inDaylightTime(new Date(julyOne - 1000)) || 490 zone.inDaylightTime(new Date(julyOne))) 491 errln("FAIL: End rule broken"); 492 493 zone.setStartYear(1991); 494 if (zone.inDaylightTime(new Date(marchOne)) || 495 zone.inDaylightTime(new Date(julyOne - 1000))) 496 errln("FAIL: Start year broken"); 497 498 // failure(status, "TestRuleAPI"); 499 // delete gc; 500 // delete zone; 501 } 502 503 void testUsingBinarySearch(SimpleTimeZone tz, long min, long max, long expectedBoundary) 504 { 505 // ErrorCode status = ZERO_ERROR; 506 boolean startsInDST = tz.inDaylightTime(new Date(min)); 507 // if (failure(status, "SimpleTimeZone::inDaylightTime")) return; 508 if (tz.inDaylightTime(new Date(max)) == startsInDST) { 509 logln("Error: inDaylightTime(" + new Date(max) + ") != " + (!startsInDST)); 510 return; 511 } 512 // if (failure(status, "SimpleTimeZone::inDaylightTime")) return; 513 while ((max - min) > INTERVAL) { 514 long mid = (min + max) / 2; 515 if (tz.inDaylightTime(new Date(mid)) == startsInDST) { 516 min = mid; 517 } 518 else { 519 max = mid; 520 } 521 // if (failure(status, "SimpleTimeZone::inDaylightTime")) return; 522 } 523 logln("Binary Search Before: " + min + " = " + new Date(min)); 524 logln("Binary Search After: " + max + " = " + new Date(max)); 525 long mindelta = expectedBoundary - min; 526 long maxdelta = max - expectedBoundary; 527 if (mindelta >= 0 && 528 mindelta <= INTERVAL && 529 mindelta >= 0 && 530 mindelta <= INTERVAL) 531 logln("PASS: Expected bdry: " + expectedBoundary + " = " + new Date(expectedBoundary)); 532 else 533 errln("FAIL: Expected bdry: " + expectedBoundary + " = " + new Date(expectedBoundary)); 534 } 535 536 static final int INTERVAL = 100; 537 538 // Bug 006; verify the offset for a specific zone. 539 public void TestPRTOffset() 540 { 541 TimeZone tz = TimeZone.getTimeZone( "PRT" ); 542 if( tz == null ) { 543 errln( "FAIL: TimeZone(PRT) is null" ); 544 } 545 else{ 546 if (tz.getRawOffset() != (-4*millisPerHour)) 547 errln("FAIL: Offset for PRT should be -4"); 548 } 549 550 } 551 552 // Test various calls 553 @SuppressWarnings("deprecation") 554 public void TestVariousAPI518() 555 { 556 TimeZone time_zone = TimeZone.getTimeZone("PST"); 557 Date d = new Date(97, Calendar.APRIL, 30); 558 559 logln("The timezone is " + time_zone.getID()); 560 561 if (time_zone.inDaylightTime(d) != true) 562 errln("FAIL: inDaylightTime returned false"); 563 564 if (time_zone.useDaylightTime() != true) 565 errln("FAIL: useDaylightTime returned false"); 566 567 if (time_zone.getRawOffset() != -8*millisPerHour) 568 errln( "FAIL: getRawOffset returned wrong value"); 569 570 GregorianCalendar gc = new GregorianCalendar(); 571 gc.setTime(d); 572 if (time_zone.getOffset(gc.AD, gc.get(gc.YEAR), gc.get(gc.MONTH), 573 gc.get(gc.DAY_OF_MONTH), 574 gc.get(gc.DAY_OF_WEEK), 0) 575 != -7*millisPerHour) 576 errln("FAIL: getOffset returned wrong value"); 577 } 578 579 // Test getAvailableID API 580 public void TestGetAvailableIDs913() 581 { 582 StringBuffer buf = new StringBuffer("TimeZone.getAvailableIDs() = { "); 583 String[] s = TimeZone.getAvailableIDs(); 584 for (int i=0; i<s.length; ++i) 585 { 586 if (i > 0) buf.append(", "); 587 buf.append(s[i]); 588 } 589 buf.append(" };"); 590 logln(buf.toString()); 591 592 buf.setLength(0); 593 buf.append("TimeZone.getAvailableIDs(GMT+02:00) = { "); 594 s = TimeZone.getAvailableIDs(+2 * 60 * 60 * 1000); 595 for (int i=0; i<s.length; ++i) 596 { 597 if (i > 0) buf.append(", "); 598 buf.append(s[i]); 599 } 600 buf.append(" };"); 601 logln(buf.toString()); 602 603 TimeZone tz = TimeZone.getTimeZone("PST"); 604 if (tz != null) 605 logln("getTimeZone(PST) = " + tz.getID()); 606 else 607 errln("FAIL: getTimeZone(PST) = null"); 608 609 tz = TimeZone.getTimeZone("America/Los_Angeles"); 610 if (tz != null) 611 logln("getTimeZone(America/Los_Angeles) = " + tz.getID()); 612 else 613 errln("FAIL: getTimeZone(PST) = null"); 614 615 // Bug 4096694 616 tz = TimeZone.getTimeZone("NON_EXISTENT"); 617 if (tz == null) 618 errln("FAIL: getTimeZone(NON_EXISTENT) = null"); 619 else if (!tz.getID().equals("GMT")) 620 errln("FAIL: getTimeZone(NON_EXISTENT) = " + tz.getID()); 621 } 622 623 /** 624 * Bug 4107276 625 */ 626 public void TestDSTSavings() { 627 // It might be better to find a way to integrate this test into the main TimeZone 628 // tests above, but I don't have time to figure out how to do this (or if it's 629 // even really a good idea). Let's consider that a future. --rtg 1/27/98 630 SimpleTimeZone tz = new SimpleTimeZone(-5 * millisPerHour, "dstSavingsTest", 631 Calendar.MARCH, 1, 0, 0, Calendar.SEPTEMBER, 1, 0, 0, 632 (int)(0.5 * millisPerHour)); 633 634 if (tz.getRawOffset() != -5 * millisPerHour) 635 errln("Got back a raw offset of " + (tz.getRawOffset() / millisPerHour) + 636 " hours instead of -5 hours."); 637 if (!tz.useDaylightTime()) 638 errln("Test time zone should use DST but claims it doesn't."); 639 if (tz.getDSTSavings() != 0.5 * millisPerHour) 640 errln("Set DST offset to 0.5 hour, but got back " + (tz.getDSTSavings() / 641 millisPerHour) + " hours instead."); 642 643 int offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.JANUARY, 1, 644 Calendar.THURSDAY, 10 * millisPerHour); 645 if (offset != -5 * millisPerHour) 646 errln("The offset for 10 AM, 1/1/98 should have been -5 hours, but we got " 647 + (offset / millisPerHour) + " hours."); 648 649 offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.JUNE, 1, Calendar.MONDAY, 650 10 * millisPerHour); 651 if (offset != -4.5 * millisPerHour) 652 errln("The offset for 10 AM, 6/1/98 should have been -4.5 hours, but we got " 653 + (offset / millisPerHour) + " hours."); 654 655 tz.setDSTSavings(millisPerHour); 656 offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.JANUARY, 1, 657 Calendar.THURSDAY, 10 * millisPerHour); 658 if (offset != -5 * millisPerHour) 659 errln("The offset for 10 AM, 1/1/98 should have been -5 hours, but we got " 660 + (offset / millisPerHour) + " hours."); 661 662 offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.JUNE, 1, Calendar.MONDAY, 663 10 * millisPerHour); 664 if (offset != -4 * millisPerHour) 665 errln("The offset for 10 AM, 6/1/98 (with a 1-hour DST offset) should have been -4 hours, but we got " 666 + (offset / millisPerHour) + " hours."); 667 } 668 669 /** 670 * Bug 4107570 671 */ 672 public void TestAlternateRules() { 673 // Like TestDSTSavings, this test should probably be integrated somehow with the main 674 // test at the top of this class, but I didn't have time to figure out how to do that. 675 // --rtg 1/28/98 676 677 SimpleTimeZone tz = new SimpleTimeZone(-5 * millisPerHour, "alternateRuleTest"); 678 679 // test the day-of-month API 680 tz.setStartRule(Calendar.MARCH, 10, 12 * millisPerHour); 681 tz.setEndRule(Calendar.OCTOBER, 20, 12 * millisPerHour); 682 683 int offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.MARCH, 5, 684 Calendar.THURSDAY, 10 * millisPerHour); 685 if (offset != -5 * millisPerHour) 686 errln("The offset for 10AM, 3/5/98 should have been -5 hours, but we got " 687 + (offset / millisPerHour) + " hours."); 688 689 offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.MARCH, 15, 690 Calendar.SUNDAY, 10 * millisPerHour); 691 if (offset != -4 * millisPerHour) 692 errln("The offset for 10AM, 3/15/98 should have been -4 hours, but we got " 693 + (offset / millisPerHour) + " hours."); 694 695 offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.OCTOBER, 15, 696 Calendar.THURSDAY, 10 * millisPerHour); 697 if (offset != -4 * millisPerHour) 698 errln("The offset for 10AM, 10/15/98 should have been -4 hours, but we got " 699 + (offset / millisPerHour) + " hours."); 700 701 offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.OCTOBER, 25, 702 Calendar.SUNDAY, 10 * millisPerHour); 703 if (offset != -5 * millisPerHour) 704 errln("The offset for 10AM, 10/25/98 should have been -5 hours, but we got " 705 + (offset / millisPerHour) + " hours."); 706 707 // test the day-of-week-after-day-in-month API 708 tz.setStartRule(Calendar.MARCH, 10, Calendar.FRIDAY, 12 * millisPerHour, true); 709 tz.setEndRule(Calendar.OCTOBER, 20, Calendar.FRIDAY, 12 * millisPerHour, false); 710 711 offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.MARCH, 11, 712 Calendar.WEDNESDAY, 10 * millisPerHour); 713 if (offset != -5 * millisPerHour) 714 errln("The offset for 10AM, 3/11/98 should have been -5 hours, but we got " 715 + (offset / millisPerHour) + " hours."); 716 717 offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.MARCH, 14, 718 Calendar.SATURDAY, 10 * millisPerHour); 719 if (offset != -4 * millisPerHour) 720 errln("The offset for 10AM, 3/14/98 should have been -4 hours, but we got " 721 + (offset / millisPerHour) + " hours."); 722 723 offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.OCTOBER, 15, 724 Calendar.THURSDAY, 10 * millisPerHour); 725 if (offset != -4 * millisPerHour) 726 errln("The offset for 10AM, 10/15/98 should have been -4 hours, but we got " 727 + (offset / millisPerHour) + " hours."); 728 729 offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.OCTOBER, 17, 730 Calendar.SATURDAY, 10 * millisPerHour); 731 if (offset != -5 * millisPerHour) 732 errln("The offset for 10AM, 10/17/98 should have been -5 hours, but we got " 733 + (offset / millisPerHour) + " hours."); 734 } 735 } 736 737 //eof