1 /* 2 * Copyright (c) 1997, 2018, 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 8181157 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("\u5317\u7f8e\u592a\u5e73\u6d0b\u6807\u51c6\u65f6\u95f4") && 368 !name.equals("GMT-08:00") && 369 !name.equals("GMT-8:00") && 370 !name.equals("GMT-0800") && 371 !name.equals("GMT-800")) { 372 errln("Fail: Expected GMT-08:00 or something similar"); 373 errln("************************************************************"); 374 errln("THE ABOVE FAILURE MAY JUST MEAN THE LOCALE DATA HAS CHANGED"); 375 errln("************************************************************"); 376 } 377 378 // Now try a non-existent zone 379 zone2 = new SimpleTimeZone(90*60*1000, "xyzzy"); 380 name = zone2.getDisplayName(Locale.ENGLISH); 381 logln("GMT+90min->" + name); 382 if (!name.equals("GMT+01:30") && 383 !name.equals("GMT+1:30") && 384 !name.equals("GMT+0130") && 385 !name.equals("GMT+130")) 386 errln("Fail: Expected GMT+01:30 or something similar"); 387 } 388 389 public void TestGenericAPI() { 390 String id = "NewGMT"; 391 int offset = 12345; 392 393 SimpleTimeZone zone = new SimpleTimeZone(offset, id); 394 if (zone.useDaylightTime()) { 395 errln("FAIL: useDaylightTime should return false"); 396 } 397 398 TimeZone zoneclone = (TimeZone)zone.clone(); 399 if (!zoneclone.equals(zone)) { 400 errln("FAIL: clone or operator== failed"); 401 } 402 zoneclone.setID("abc"); 403 if (zoneclone.equals(zone)) { 404 errln("FAIL: clone or operator!= failed"); 405 } 406 407 zoneclone = (TimeZone)zone.clone(); 408 if (!zoneclone.equals(zone)) { 409 errln("FAIL: clone or operator== failed"); 410 } 411 zoneclone.setRawOffset(45678); 412 if (zoneclone.equals(zone)) { 413 errln("FAIL: clone or operator!= failed"); 414 } 415 416 TimeZone saveDefault = TimeZone.getDefault(); 417 try { 418 TimeZone.setDefault(zone); 419 TimeZone defaultzone = TimeZone.getDefault(); 420 if (defaultzone == zone) { 421 errln("FAIL: Default object is identical, not clone"); 422 } 423 if (!defaultzone.equals(zone)) { 424 errln("FAIL: Default object is not equal"); 425 } 426 } 427 finally { 428 TimeZone.setDefault(saveDefault); 429 } 430 } 431 432 @SuppressWarnings("deprecation") 433 public void TestRuleAPI() 434 { 435 // ErrorCode status = ZERO_ERROR; 436 437 int offset = (int)(60*60*1000*1.75); // Pick a weird offset 438 SimpleTimeZone zone = new SimpleTimeZone(offset, "TestZone"); 439 if (zone.useDaylightTime()) errln("FAIL: useDaylightTime should return false"); 440 441 // Establish our expected transition times. Do this with a non-DST 442 // calendar with the (above) declared local offset. 443 GregorianCalendar gc = new GregorianCalendar(zone); 444 gc.clear(); 445 gc.set(1990, Calendar.MARCH, 1); 446 long marchOneStd = gc.getTime().getTime(); // Local Std time midnight 447 gc.clear(); 448 gc.set(1990, Calendar.JULY, 1); 449 long julyOneStd = gc.getTime().getTime(); // Local Std time midnight 450 451 // Starting and ending hours, WALL TIME 452 int startHour = (int)(2.25 * 3600000); 453 int endHour = (int)(3.5 * 3600000); 454 455 zone.setStartRule(Calendar.MARCH, 1, 0, startHour); 456 zone.setEndRule (Calendar.JULY, 1, 0, endHour); 457 458 gc = new GregorianCalendar(zone); 459 // if (failure(status, "new GregorianCalendar")) return; 460 461 long marchOne = marchOneStd + startHour; 462 long julyOne = julyOneStd + endHour - 3600000; // Adjust from wall to Std time 463 464 long expMarchOne = 636251400000L; 465 if (marchOne != expMarchOne) 466 { 467 errln("FAIL: Expected start computed as " + marchOne + 468 " = " + new Date(marchOne)); 469 logln(" Should be " + expMarchOne + 470 " = " + new Date(expMarchOne)); 471 } 472 473 long expJulyOne = 646793100000L; 474 if (julyOne != expJulyOne) 475 { 476 errln("FAIL: Expected start computed as " + julyOne + 477 " = " + new Date(julyOne)); 478 logln(" Should be " + expJulyOne + 479 " = " + new Date(expJulyOne)); 480 } 481 482 testUsingBinarySearch(zone, new Date(90, Calendar.JANUARY, 1).getTime(), 483 new Date(90, Calendar.JUNE, 15).getTime(), marchOne); 484 testUsingBinarySearch(zone, new Date(90, Calendar.JUNE, 1).getTime(), 485 new Date(90, Calendar.DECEMBER, 31).getTime(), julyOne); 486 487 if (zone.inDaylightTime(new Date(marchOne - 1000)) || 488 !zone.inDaylightTime(new Date(marchOne))) 489 errln("FAIL: Start rule broken"); 490 if (!zone.inDaylightTime(new Date(julyOne - 1000)) || 491 zone.inDaylightTime(new Date(julyOne))) 492 errln("FAIL: End rule broken"); 493 494 zone.setStartYear(1991); 495 if (zone.inDaylightTime(new Date(marchOne)) || 496 zone.inDaylightTime(new Date(julyOne - 1000))) 497 errln("FAIL: Start year broken"); 498 499 // failure(status, "TestRuleAPI"); 500 // delete gc; 501 // delete zone; 502 } 503 504 void testUsingBinarySearch(SimpleTimeZone tz, long min, long max, long expectedBoundary) 505 { 506 // ErrorCode status = ZERO_ERROR; 507 boolean startsInDST = tz.inDaylightTime(new Date(min)); 508 // if (failure(status, "SimpleTimeZone::inDaylightTime")) return; 509 if (tz.inDaylightTime(new Date(max)) == startsInDST) { 510 logln("Error: inDaylightTime(" + new Date(max) + ") != " + (!startsInDST)); 511 return; 512 } 513 // if (failure(status, "SimpleTimeZone::inDaylightTime")) return; 514 while ((max - min) > INTERVAL) { 515 long mid = (min + max) / 2; 516 if (tz.inDaylightTime(new Date(mid)) == startsInDST) { 517 min = mid; 518 } 519 else { 520 max = mid; 521 } 522 // if (failure(status, "SimpleTimeZone::inDaylightTime")) return; 523 } 524 logln("Binary Search Before: " + min + " = " + new Date(min)); 525 logln("Binary Search After: " + max + " = " + new Date(max)); 526 long mindelta = expectedBoundary - min; 527 long maxdelta = max - expectedBoundary; 528 if (mindelta >= 0 && 529 mindelta <= INTERVAL && 530 mindelta >= 0 && 531 mindelta <= INTERVAL) 532 logln("PASS: Expected bdry: " + expectedBoundary + " = " + new Date(expectedBoundary)); 533 else 534 errln("FAIL: Expected bdry: " + expectedBoundary + " = " + new Date(expectedBoundary)); 535 } 536 537 static final int INTERVAL = 100; 538 539 // Bug 006; verify the offset for a specific zone. 540 public void TestPRTOffset() 541 { 542 TimeZone tz = TimeZone.getTimeZone( "PRT" ); 543 if( tz == null ) { 544 errln( "FAIL: TimeZone(PRT) is null" ); 545 } 546 else{ 547 if (tz.getRawOffset() != (-4*millisPerHour)) 548 errln("FAIL: Offset for PRT should be -4"); 549 } 550 551 } 552 553 // Test various calls 554 @SuppressWarnings("deprecation") 555 public void TestVariousAPI518() 556 { 557 TimeZone time_zone = TimeZone.getTimeZone("PST"); 558 Date d = new Date(97, Calendar.APRIL, 30); 559 560 logln("The timezone is " + time_zone.getID()); 561 562 if (time_zone.inDaylightTime(d) != true) 563 errln("FAIL: inDaylightTime returned false"); 564 565 if (time_zone.useDaylightTime() != true) 566 errln("FAIL: useDaylightTime returned false"); 567 568 if (time_zone.getRawOffset() != -8*millisPerHour) 569 errln( "FAIL: getRawOffset returned wrong value"); 570 571 GregorianCalendar gc = new GregorianCalendar(); 572 gc.setTime(d); 573 if (time_zone.getOffset(gc.AD, gc.get(gc.YEAR), gc.get(gc.MONTH), 574 gc.get(gc.DAY_OF_MONTH), 575 gc.get(gc.DAY_OF_WEEK), 0) 576 != -7*millisPerHour) 577 errln("FAIL: getOffset returned wrong value"); 578 } 579 580 // Test getAvailableID API 581 public void TestGetAvailableIDs913() 582 { 583 StringBuffer buf = new StringBuffer("TimeZone.getAvailableIDs() = { "); 584 String[] s = TimeZone.getAvailableIDs(); 585 for (int i=0; i<s.length; ++i) 586 { 587 if (i > 0) buf.append(", "); 588 buf.append(s[i]); 589 } 590 buf.append(" };"); 591 logln(buf.toString()); 592 593 buf.setLength(0); 594 buf.append("TimeZone.getAvailableIDs(GMT+02:00) = { "); 595 s = TimeZone.getAvailableIDs(+2 * 60 * 60 * 1000); 596 for (int i=0; i<s.length; ++i) 597 { 598 if (i > 0) buf.append(", "); 599 buf.append(s[i]); 600 } 601 buf.append(" };"); 602 logln(buf.toString()); 603 604 TimeZone tz = TimeZone.getTimeZone("PST"); 605 if (tz != null) 606 logln("getTimeZone(PST) = " + tz.getID()); 607 else 608 errln("FAIL: getTimeZone(PST) = null"); 609 610 tz = TimeZone.getTimeZone("America/Los_Angeles"); 611 if (tz != null) 612 logln("getTimeZone(America/Los_Angeles) = " + tz.getID()); 613 else 614 errln("FAIL: getTimeZone(PST) = null"); 615 616 // Bug 4096694 617 tz = TimeZone.getTimeZone("NON_EXISTENT"); 618 if (tz == null) 619 errln("FAIL: getTimeZone(NON_EXISTENT) = null"); 620 else if (!tz.getID().equals("GMT")) 621 errln("FAIL: getTimeZone(NON_EXISTENT) = " + tz.getID()); 622 } 623 624 /** 625 * Bug 4107276 626 */ 627 public void TestDSTSavings() { 628 // It might be better to find a way to integrate this test into the main TimeZone 629 // tests above, but I don't have time to figure out how to do this (or if it's 630 // even really a good idea). Let's consider that a future. --rtg 1/27/98 631 SimpleTimeZone tz = new SimpleTimeZone(-5 * millisPerHour, "dstSavingsTest", 632 Calendar.MARCH, 1, 0, 0, Calendar.SEPTEMBER, 1, 0, 0, 633 (int)(0.5 * millisPerHour)); 634 635 if (tz.getRawOffset() != -5 * millisPerHour) 636 errln("Got back a raw offset of " + (tz.getRawOffset() / millisPerHour) + 637 " hours instead of -5 hours."); 638 if (!tz.useDaylightTime()) 639 errln("Test time zone should use DST but claims it doesn't."); 640 if (tz.getDSTSavings() != 0.5 * millisPerHour) 641 errln("Set DST offset to 0.5 hour, but got back " + (tz.getDSTSavings() / 642 millisPerHour) + " hours instead."); 643 644 int offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.JANUARY, 1, 645 Calendar.THURSDAY, 10 * millisPerHour); 646 if (offset != -5 * millisPerHour) 647 errln("The offset for 10 AM, 1/1/98 should have been -5 hours, but we got " 648 + (offset / millisPerHour) + " hours."); 649 650 offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.JUNE, 1, Calendar.MONDAY, 651 10 * millisPerHour); 652 if (offset != -4.5 * millisPerHour) 653 errln("The offset for 10 AM, 6/1/98 should have been -4.5 hours, but we got " 654 + (offset / millisPerHour) + " hours."); 655 656 tz.setDSTSavings(millisPerHour); 657 offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.JANUARY, 1, 658 Calendar.THURSDAY, 10 * millisPerHour); 659 if (offset != -5 * millisPerHour) 660 errln("The offset for 10 AM, 1/1/98 should have been -5 hours, but we got " 661 + (offset / millisPerHour) + " hours."); 662 663 offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.JUNE, 1, Calendar.MONDAY, 664 10 * millisPerHour); 665 if (offset != -4 * millisPerHour) 666 errln("The offset for 10 AM, 6/1/98 (with a 1-hour DST offset) should have been -4 hours, but we got " 667 + (offset / millisPerHour) + " hours."); 668 } 669 670 /** 671 * Bug 4107570 672 */ 673 public void TestAlternateRules() { 674 // Like TestDSTSavings, this test should probably be integrated somehow with the main 675 // test at the top of this class, but I didn't have time to figure out how to do that. 676 // --rtg 1/28/98 677 678 SimpleTimeZone tz = new SimpleTimeZone(-5 * millisPerHour, "alternateRuleTest"); 679 680 // test the day-of-month API 681 tz.setStartRule(Calendar.MARCH, 10, 12 * millisPerHour); 682 tz.setEndRule(Calendar.OCTOBER, 20, 12 * millisPerHour); 683 684 int offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.MARCH, 5, 685 Calendar.THURSDAY, 10 * millisPerHour); 686 if (offset != -5 * millisPerHour) 687 errln("The offset for 10AM, 3/5/98 should have been -5 hours, but we got " 688 + (offset / millisPerHour) + " hours."); 689 690 offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.MARCH, 15, 691 Calendar.SUNDAY, 10 * millisPerHour); 692 if (offset != -4 * millisPerHour) 693 errln("The offset for 10AM, 3/15/98 should have been -4 hours, but we got " 694 + (offset / millisPerHour) + " hours."); 695 696 offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.OCTOBER, 15, 697 Calendar.THURSDAY, 10 * millisPerHour); 698 if (offset != -4 * millisPerHour) 699 errln("The offset for 10AM, 10/15/98 should have been -4 hours, but we got " 700 + (offset / millisPerHour) + " hours."); 701 702 offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.OCTOBER, 25, 703 Calendar.SUNDAY, 10 * millisPerHour); 704 if (offset != -5 * millisPerHour) 705 errln("The offset for 10AM, 10/25/98 should have been -5 hours, but we got " 706 + (offset / millisPerHour) + " hours."); 707 708 // test the day-of-week-after-day-in-month API 709 tz.setStartRule(Calendar.MARCH, 10, Calendar.FRIDAY, 12 * millisPerHour, true); 710 tz.setEndRule(Calendar.OCTOBER, 20, Calendar.FRIDAY, 12 * millisPerHour, false); 711 712 offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.MARCH, 11, 713 Calendar.WEDNESDAY, 10 * millisPerHour); 714 if (offset != -5 * millisPerHour) 715 errln("The offset for 10AM, 3/11/98 should have been -5 hours, but we got " 716 + (offset / millisPerHour) + " hours."); 717 718 offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.MARCH, 14, 719 Calendar.SATURDAY, 10 * millisPerHour); 720 if (offset != -4 * millisPerHour) 721 errln("The offset for 10AM, 3/14/98 should have been -4 hours, but we got " 722 + (offset / millisPerHour) + " hours."); 723 724 offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.OCTOBER, 15, 725 Calendar.THURSDAY, 10 * millisPerHour); 726 if (offset != -4 * millisPerHour) 727 errln("The offset for 10AM, 10/15/98 should have been -4 hours, but we got " 728 + (offset / millisPerHour) + " hours."); 729 730 offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.OCTOBER, 17, 731 Calendar.SATURDAY, 10 * millisPerHour); 732 if (offset != -5 * millisPerHour) 733 errln("The offset for 10AM, 10/17/98 should have been -5 hours, but we got " 734 + (offset / millisPerHour) + " hours."); 735 } 736 } 737 738 //eof