1 /** 2 ******************************************************************************* 3 * Copyright (C) 2000-2015, International Business Machines Corporation and * 4 * others. All Rights Reserved. * 5 ******************************************************************************* 6 */ 7 8 package com.ibm.icu.dev.test.timezone; 9 10 import java.io.ByteArrayInputStream; 11 import java.io.ByteArrayOutputStream; 12 import java.io.IOException; 13 import java.io.ObjectInputStream; 14 import java.io.ObjectOutputStream; 15 import java.lang.reflect.InvocationTargetException; 16 import java.util.Arrays; 17 import java.util.Date; 18 import java.util.List; 19 import java.util.Locale; 20 import java.util.Set; 21 22 import com.ibm.icu.dev.test.TestFmwk; 23 import com.ibm.icu.impl.ICUResourceBundle; 24 import com.ibm.icu.text.SimpleDateFormat; 25 import com.ibm.icu.util.BasicTimeZone; 26 import com.ibm.icu.util.Calendar; 27 import com.ibm.icu.util.DateTimeRule; 28 import com.ibm.icu.util.GregorianCalendar; 29 import com.ibm.icu.util.InitialTimeZoneRule; 30 import com.ibm.icu.util.RuleBasedTimeZone; 31 import com.ibm.icu.util.SimpleTimeZone; 32 import com.ibm.icu.util.TimeArrayTimeZoneRule; 33 import com.ibm.icu.util.TimeZone; 34 import com.ibm.icu.util.TimeZone.SystemTimeZoneType; 35 import com.ibm.icu.util.TimeZoneRule; 36 import com.ibm.icu.util.TimeZoneTransition; 37 import com.ibm.icu.util.ULocale; 38 import com.ibm.icu.util.UResourceBundle; 39 import com.ibm.icu.util.VTimeZone; 40 import com.ibm.icu.util.VersionInfo; 41 42 /** 43 * @test 1.22 99/09/21 44 * @bug 4028006 4044013 4096694 4107276 4107570 4112869 4130885 45 * @summary test TimeZone 46 * @build TimeZoneTest 47 */ 48 public class TimeZoneTest extends TestFmwk 49 { 50 static final int millisPerHour = 3600000; 51 52 // Some test case data is current date/tzdata version sensitive and producing errors 53 // when year/rule are changed. Although we want to keep our eyes on test failures 54 // caused by tzdata changes while development, keep maintaining test data in maintenance 55 // stream is a little bit hassle. ICU 49 or later versions are using minor version field 56 // to indicate a development build (0) or official release build (others). For development 57 // builds, a test failure triggers an error, while release builds only report them in 58 // verbose mode with logln. 59 static final boolean isDevelopmentBuild = (VersionInfo.ICU_VERSION.getMinor() == 0); 60 61 public static void main(String[] args) throws Exception { 62 new TimeZoneTest().run(args); 63 } 64 65 /** 66 * NOTE: As of ICU 2.8, the mapping of 3-letter legacy aliases 67 * to `real' Olson IDs is under control of the underlying JDK. 68 * This test may fail on one JDK and pass on another; don't be 69 * too concerned. Alan 70 * 71 * Bug 4130885 72 * Certain short zone IDs, used since 1.1.x, are incorrect. 73 * 74 * The worst of these is: 75 * 76 * "CAT" (Central African Time) should be GMT+2:00, but instead returns a 77 * zone at GMT-1:00. The zone at GMT-1:00 should be called EGT, CVT, EGST, 78 * or AZOST, depending on which zone is meant, but in no case is it CAT. 79 * 80 * Other wrong zone IDs: 81 * 82 * ECT (European Central Time) GMT+1:00: ECT is Ecuador Time, 83 * GMT-5:00. European Central time is abbreviated CEST. 84 * 85 * SST (Solomon Island Time) GMT+11:00. SST is actually Samoa Standard Time, 86 * GMT-11:00. Solomon Island time is SBT. 87 * 88 * NST (New Zealand Time) GMT+12:00. NST is the abbreviation for 89 * Newfoundland Standard Time, GMT-3:30. New Zealanders use NZST. 90 * 91 * AST (Alaska Standard Time) GMT-9:00. [This has already been noted in 92 * another bug.] It should be "AKST". AST is Atlantic Standard Time, 93 * GMT-4:00. 94 * 95 * PNT (Phoenix Time) GMT-7:00. PNT usually means Pitcairn Time, 96 * GMT-8:30. There is no standard abbreviation for Phoenix time, as distinct 97 * from MST with daylight savings. 98 * 99 * In addition to these problems, a number of zones are FAKE. That is, they 100 * don't match what people use in the real world. 101 * 102 * FAKE zones: 103 * 104 * EET (should be EEST) 105 * ART (should be EEST) 106 * MET (should be IRST) 107 * NET (should be AMST) 108 * PLT (should be PKT) 109 * BST (should be BDT) 110 * VST (should be ICT) 111 * CTT (should be CST) + 112 * ACT (should be CST) + 113 * AET (should be EST) + 114 * MIT (should be WST) + 115 * IET (should be EST) + 116 * PRT (should be AST) + 117 * CNT (should be NST) 118 * AGT (should be ARST) 119 * BET (should be EST) + 120 * 121 * + A zone with the correct name already exists and means something 122 * else. E.g., EST usually indicates the US Eastern zone, so it cannot be 123 * used for Brazil (BET). 124 */ 125 public void TestShortZoneIDs() throws Exception { 126 127 // Note: If the default TimeZone type is JDK, some time zones 128 // may differ from the test data below. For example, "MST" on 129 // IBM JRE is an alias of "America/Denver" for supporting Java 1.1 130 // backward compatibility, while Olson tzdata (and ICU) treat it 131 // as -7hour fixed offset/no DST. 132 boolean isJDKTimeZone = (TimeZone.getDefaultTimeZoneType() == TimeZone.TIMEZONE_JDK); 133 if (isJDKTimeZone) { 134 logln("Warning: Using JDK TimeZone. Some test cases may not return expected results."); 135 } 136 137 ZoneDescriptor[] REFERENCE_LIST = { 138 new ZoneDescriptor("HST", -600, false), // Olson northamerica -10:00 139 new ZoneDescriptor("AST", -540, true), // ICU Link - America/Anchorage 140 new ZoneDescriptor("PST", -480, true), // ICU Link - America/Los_Angeles 141 new ZoneDescriptor("PNT", -420, false), // ICU Link - America/Phoenix 142 new ZoneDescriptor("MST", -420, false), // updated Aug 2003 aliu 143 new ZoneDescriptor("CST", -360, true), // Olson northamerica -7:00 144 new ZoneDescriptor("IET", -300, true), // ICU Link - America/Indiana/Indianapolis 145 new ZoneDescriptor("EST", -300, false), // Olson northamerica -5:00 146 new ZoneDescriptor("PRT", -240, false), // ICU Link - America/Puerto_Rico 147 new ZoneDescriptor("CNT", -210, true), // ICU Link - America/St_Johns 148 new ZoneDescriptor("AGT", -180, false), // ICU Link - America/Argentina/Buenos_Aires 149 new ZoneDescriptor("BET", -180, true), // ICU Link - America/Sao_Paulo 150 new ZoneDescriptor("GMT", 0, false), // Olson etcetera Link - Etc/GMT 151 new ZoneDescriptor("UTC", 0, false), // Olson etcetera 0 152 new ZoneDescriptor("ECT", 60, true), // ICU Link - Europe/Paris 153 new ZoneDescriptor("MET", 60, true), // Olson europe 1:00 C-Eur 154 new ZoneDescriptor("CAT", 120, false), // ICU Link - Africa/Harare 155 new ZoneDescriptor("ART", 120, false), // ICU Link - Africa/Cairo 156 new ZoneDescriptor("EET", 120, true), // Olson europe 2:00 EU 157 new ZoneDescriptor("EAT", 180, false), // ICU Link - Africa/Addis_Ababa 158 new ZoneDescriptor("NET", 240, false), // ICU Link - Asia/Yerevan 159 new ZoneDescriptor("PLT", 300, false), // ICU Link - Asia/Karachi 160 new ZoneDescriptor("IST", 330, false), // ICU Link - Asia/Kolkata 161 new ZoneDescriptor("BST", 360, false), // ICU Link - Asia/Dhaka 162 new ZoneDescriptor("VST", 420, false), // ICU Link - Asia/Ho_Chi_Minh 163 new ZoneDescriptor("CTT", 480, false), // ICU Link - Asia/Shanghai 164 new ZoneDescriptor("JST", 540, false), // ICU Link - Asia/Tokyo 165 new ZoneDescriptor("ACT", 570, false), // ICU Link - Australia/Darwin 166 new ZoneDescriptor("AET", 600, true), // ICU Link - Australia/Sydney 167 new ZoneDescriptor("SST", 660, false), // ICU Link - Pacific/Guadalcanal 168 new ZoneDescriptor("NST", 720, true), // ICU Link - Pacific/Auckland 169 new ZoneDescriptor("MIT", 780, true), // ICU Link - Pacific/Apia 170 171 new ZoneDescriptor("Etc/Unknown", 0, false), // CLDR 172 173 new ZoneDescriptor("SystemV/AST4ADT", -240, true), 174 new ZoneDescriptor("SystemV/EST5EDT", -300, true), 175 new ZoneDescriptor("SystemV/CST6CDT", -360, true), 176 new ZoneDescriptor("SystemV/MST7MDT", -420, true), 177 new ZoneDescriptor("SystemV/PST8PDT", -480, true), 178 new ZoneDescriptor("SystemV/YST9YDT", -540, true), 179 new ZoneDescriptor("SystemV/AST4", -240, false), 180 new ZoneDescriptor("SystemV/EST5", -300, false), 181 new ZoneDescriptor("SystemV/CST6", -360, false), 182 new ZoneDescriptor("SystemV/MST7", -420, false), 183 new ZoneDescriptor("SystemV/PST8", -480, false), 184 new ZoneDescriptor("SystemV/YST9", -540, false), 185 new ZoneDescriptor("SystemV/HST10", -600, false), 186 }; 187 188 for (int i=0; i<REFERENCE_LIST.length; ++i) { 189 ZoneDescriptor referenceZone = REFERENCE_LIST[i]; 190 ZoneDescriptor currentZone = new ZoneDescriptor(TimeZone.getTimeZone(referenceZone.getID())); 191 if (referenceZone.equals(currentZone)) { 192 logln("ok " + referenceZone); 193 } 194 else { 195 if (!isDevelopmentBuild || isJDKTimeZone) { 196 logln("Warning: Expected " + referenceZone + 197 "; got " + currentZone); 198 } else { 199 errln("Fail: Expected " + referenceZone + 200 "; got " + currentZone); 201 } 202 } 203 } 204 } 205 206 /** 207 * A descriptor for a zone; used to regress the short zone IDs. 208 */ 209 static class ZoneDescriptor { 210 String id; 211 int offset; // In minutes 212 boolean daylight; 213 214 ZoneDescriptor(TimeZone zone) { 215 this.id = zone.getID(); 216 this.offset = zone.getRawOffset() / 60000; 217 this.daylight = zone.useDaylightTime(); 218 } 219 220 ZoneDescriptor(String id, int offset, boolean daylight) { 221 this.id = id; 222 this.offset = offset; 223 this.daylight = daylight; 224 } 225 226 public String getID() { return id; } 227 228 public boolean equals(Object o) { 229 ZoneDescriptor that = (ZoneDescriptor)o; 230 return that != null && 231 id.equals(that.id) && 232 offset == that.offset && 233 daylight == that.daylight; 234 } 235 236 public String toString() { 237 int min = offset; 238 char sign = '+'; 239 if (min < 0) { sign = '-'; min = -min; } 240 241 return "Zone[\"" + id + "\", GMT" + sign + (min/60) + ':' + 242 (min%60<10?"0":"") + (min%60) + ", " + 243 (daylight ? "Daylight" : "Standard") + "]"; 244 } 245 246 public static int compare(Object o1, Object o2) { 247 ZoneDescriptor i1 = (ZoneDescriptor)o1; 248 ZoneDescriptor i2 = (ZoneDescriptor)o2; 249 if (i1.offset > i2.offset) return 1; 250 if (i1.offset < i2.offset) return -1; 251 if (i1.daylight && !i2.daylight) return 1; 252 if (!i1.daylight && i2.daylight) return -1; 253 return i1.id.compareTo(i2.id); 254 } 255 } 256 257 /** 258 * As part of the VM fix (see CCC approved RFE 4028006, bug 259 * 4044013), TimeZone.getTimeZone() has been modified to recognize 260 * generic IDs of the form GMT[+-]hh:mm, GMT[+-]hhmm, and 261 * GMT[+-]hh. Test this behavior here. 262 * 263 * Bug 4044013 264 */ 265 public void TestCustomParse() { 266 String[] DATA = { 267 // ID offset(sec) output ID 268 "GMT", "0", "GMT", // system ID 269 "GMT-YOUR.AD.HERE", "0", TimeZone.UNKNOWN_ZONE_ID, 270 "GMT0", "0", "GMT0", // system ID 271 "GMT+0", "0", "GMT+0", // system ID 272 "GMT+1", "3600", "GMT+01:00", 273 "GMT-0030", "-1800", "GMT-00:30", 274 "GMT+15:99", "0", TimeZone.UNKNOWN_ZONE_ID, 275 "GMT+", "0", TimeZone.UNKNOWN_ZONE_ID, 276 "GMT-", "0", TimeZone.UNKNOWN_ZONE_ID, 277 "GMT+0:", "0", TimeZone.UNKNOWN_ZONE_ID, 278 "GMT-:", "0", TimeZone.UNKNOWN_ZONE_ID, 279 "GMT+0010", "600", "GMT+00:10", 280 "GMT-10", "-36000", "GMT-10:00", 281 "GMT+30", "0", TimeZone.UNKNOWN_ZONE_ID, 282 "GMT-3:30", "-12600", "GMT-03:30", 283 "GMT-230", "-9000", "GMT-02:30", 284 "GMT+05:13:05", "18785", "GMT+05:13:05", 285 "GMT-71023", "-25823", "GMT-07:10:23", 286 "GMT+01:23:45:67", "0", TimeZone.UNKNOWN_ZONE_ID, 287 "GMT+01:234", "0", TimeZone.UNKNOWN_ZONE_ID, 288 "GMT-2:31:123", "0", TimeZone.UNKNOWN_ZONE_ID, 289 "GMT+3:75", "0", TimeZone.UNKNOWN_ZONE_ID, 290 "GMT-01010101", "0", TimeZone.UNKNOWN_ZONE_ID, 291 }; 292 for (int i = 0; i < DATA.length; i += 3) { 293 String id = DATA[i]; 294 int offset = Integer.parseInt(DATA[i+1]); 295 String expId = DATA[i+2]; 296 297 TimeZone zone = TimeZone.getTimeZone(id); 298 String gotID = zone.getID(); 299 int gotOffset = zone.getRawOffset()/1000; 300 301 logln(id + " -> " + gotID + " " + gotOffset); 302 303 if (offset != gotOffset) { 304 errln("FAIL: Unexpected offset for " + id + " - returned:" + gotOffset + " expected:" + offset); 305 } 306 if (!expId.equals(gotID)) { 307 if (TimeZone.getDefaultTimeZoneType() != TimeZone.TIMEZONE_ICU) { 308 logln("ID for " + id + " - returned:" + gotID + " expected:" + expId); 309 } else { 310 errln("FAIL: Unexpected ID for " + id + " - returned:" + gotID + " expected:" + expId); 311 } 312 } 313 } 314 } 315 316 /** 317 * Test the basic functionality of the getDisplayName() API. 318 * 319 * Bug 4112869 320 * Bug 4028006 321 * 322 * See also API change request A41. 323 * 324 * 4/21/98 - make smarter, so the test works if the ext resources 325 * are present or not. 326 */ 327 public void TestDisplayName() { 328 TimeZone zone = TimeZone.getTimeZone("PST"); 329 String name = zone.getDisplayName(Locale.ENGLISH); 330 logln("PST->" + name); 331 332 // dlf - we now (3.4.1) return generic time 333 if (!name.equals("Pacific Time")) 334 errln("Fail: Expected \"Pacific Time\", got " + name + 335 " for " + zone); 336 337 //***************************************************************** 338 // THE FOLLOWING LINES MUST BE UPDATED IF THE LOCALE DATA CHANGES 339 // THE FOLLOWING LINES MUST BE UPDATED IF THE LOCALE DATA CHANGES 340 // THE FOLLOWING LINES MUST BE UPDATED IF THE LOCALE DATA CHANGES 341 //***************************************************************** 342 343 // Test to allow the user to choose to get all the forms 344 // (z, zzzz, Z, ZZZZ, v, vvvv) 345 // todo: check to see whether we can test for all of pst, pdt, pt 346 Object[] DATA = { 347 // z and zzzz 348 Boolean.FALSE, new Integer(TimeZone.SHORT), "PST", 349 Boolean.TRUE, new Integer(TimeZone.SHORT), "PDT", 350 Boolean.FALSE, new Integer(TimeZone.LONG), "Pacific Standard Time", 351 Boolean.TRUE, new Integer(TimeZone.LONG), "Pacific Daylight Time", 352 // v and vvvv 353 Boolean.FALSE, new Integer(TimeZone.SHORT_GENERIC), "PT", 354 Boolean.TRUE, new Integer(TimeZone.SHORT_GENERIC), "PT", 355 Boolean.FALSE, new Integer(TimeZone.LONG_GENERIC), "Pacific Time", 356 Boolean.TRUE, new Integer(TimeZone.LONG_GENERIC), "Pacific Time", 357 // z and ZZZZ 358 Boolean.FALSE, new Integer(TimeZone.SHORT_GMT), "-0800", 359 Boolean.TRUE, new Integer(TimeZone.SHORT_GMT), "-0700", 360 Boolean.FALSE, new Integer(TimeZone.LONG_GMT), "GMT-08:00", 361 Boolean.TRUE, new Integer(TimeZone.LONG_GMT), "GMT-07:00", 362 // V and VVVV 363 Boolean.FALSE, new Integer(TimeZone.SHORT_COMMONLY_USED), "PST", 364 Boolean.TRUE, new Integer(TimeZone.SHORT_COMMONLY_USED), "PDT", 365 Boolean.FALSE, new Integer(TimeZone.GENERIC_LOCATION), "Los Angeles Time", 366 Boolean.TRUE, new Integer(TimeZone.GENERIC_LOCATION), "Los Angeles Time", 367 }; 368 369 for (int i=0; i<DATA.length; i+=3) { 370 name = zone.getDisplayName(((Boolean)DATA[i]).booleanValue(), 371 ((Integer)DATA[i+1]).intValue(), 372 Locale.ENGLISH); 373 if (!name.equals(DATA[i+2])) 374 errln("Fail: Expected " + DATA[i+2] + "; got " + name); 375 } 376 377 // Make sure that we don't display the DST name by constructing a fake 378 // PST zone that has DST all year long. 379 // dlf - this test is no longer relevant, we display generic time now 380 // so the behavior of the timezone doesn't matter 381 SimpleTimeZone zone2 = new SimpleTimeZone(0, "PST"); 382 zone2.setStartRule(Calendar.JANUARY, 1, 0); 383 zone2.setEndRule(Calendar.DECEMBER, 31, 86399999); 384 logln("Modified PST inDaylightTime->" + zone2.inDaylightTime(new Date())); 385 name = zone2.getDisplayName(Locale.ENGLISH); 386 logln("Modified PST->" + name); 387 if (!name.equals("Pacific Time")) 388 errln("Fail: Expected \"Pacific Time\""); 389 390 // Make sure we get the default display format for Locales 391 // with no display name data. 392 Locale mt_MT = new Locale("mt", "MT"); 393 name = zone.getDisplayName(mt_MT); 394 //***************************************************************** 395 // THE FOLLOWING LINE MUST BE UPDATED IF THE LOCALE DATA CHANGES 396 // THE FOLLOWING LINE MUST BE UPDATED IF THE LOCALE DATA CHANGES 397 // THE FOLLOWING LINE MUST BE UPDATED IF THE LOCALE DATA CHANGES 398 //***************************************************************** 399 logln("PST(mt_MT)->" + name); 400 401 // Now be smart -- check to see if zh resource is even present. 402 // If not, we expect the en fallback behavior. 403 404 // in icu4j 2.1 we know we have the zh_CN locale data, though it's incomplete 405 // /"DateFormatZoneData", 406 UResourceBundle enRB = UResourceBundle.getBundleInstance(ICUResourceBundle.ICU_BASE_NAME,Locale.ENGLISH); 407 UResourceBundle mtRB = UResourceBundle.getBundleInstance(ICUResourceBundle.ICU_BASE_NAME, mt_MT); 408 boolean noZH = enRB == mtRB; 409 410 if (noZH) { 411 logln("Warning: Not testing the mt_MT behavior because resource is absent"); 412 if (!name.equals("Pacific Standard Time")) 413 errln("Fail: Expected Pacific Standard Time for PST in mt_MT but got "); 414 } 415 // dlf - we will use generic time, or if unavailable, GMT for standard time in the zone 416 // - we now (3.4.1) have localizations for this zone, so change test string 417 else if(!name.equals("\u0126in ta\u2019 Los Angeles") && 418 !name.equals("GMT-08:00") && 419 !name.equals("GMT-8:00") && 420 !name.equals("GMT-0800") && 421 !name.equals("GMT-800")) { 422 423 errln("Fail: got '" + name + "', expected GMT-08:00 or something similar\n" + 424 "************************************************************\n" + 425 "THE ABOVE FAILURE MAY JUST MEAN THE LOCALE DATA HAS CHANGED\n" + 426 "************************************************************"); 427 } 428 429 // Now try a non-existent zone 430 zone2 = new SimpleTimeZone(90*60*1000, "xyzzy"); 431 name = zone2.getDisplayName(Locale.ENGLISH); 432 logln("GMT+90min->" + name); 433 if (!name.equals("GMT+01:30") && 434 !name.equals("GMT+1:30") && 435 !name.equals("GMT+0130") && 436 !name.equals("GMT+130")) 437 errln("Fail: Expected GMT+01:30 or something similar"); 438 439 // cover getDisplayName() - null arg 440 ULocale save = ULocale.getDefault(); 441 ULocale.setDefault(ULocale.US); 442 name = zone2.getDisplayName(); 443 logln("GMT+90min->" + name + "for default display locale"); 444 if (!name.equals("GMT+01:30") && 445 !name.equals("GMT+1:30") && 446 !name.equals("GMT+0130") && 447 !name.equals("GMT+130")) 448 errln("Fail: Expected GMT+01:30 or something similar"); 449 ULocale.setDefault(save); 450 451 } 452 453 454 public void TestDisplayName2() { 455 Date now = new Date(); 456 457 String[] timezones = {"America/Chicago", "Europe/Moscow", "Europe/Rome", "Asia/Shanghai", "WET" }; 458 String[] locales = {"en", "fr", "de", "ja", "zh_TW", "zh_Hans" }; 459 for (int j = 0; j < locales.length; ++j) { 460 ULocale locale = new ULocale(locales[j]); 461 for (int i = 0; i < timezones.length; ++i) { 462 TimeZone tz = TimeZone.getTimeZone(timezones[i]); 463 String displayName0 = tz.getDisplayName(locale); 464 SimpleDateFormat dt = new SimpleDateFormat("vvvv", locale); 465 dt.setTimeZone(tz); 466 String displayName1 = dt.format(now); // date value _does_ matter if we fallback to GMT 467 logln(locale.getDisplayName() + ", " + tz.getID() + ": " + displayName0); 468 if (!displayName1.equals(displayName0)) { 469 // This could happen when the date used is in DST, 470 // because TimeZone.getDisplayName(ULocale) may use 471 // localized GMT format for the time zone's standard 472 // time. 473 if (tz.inDaylightTime(now)) { 474 // Try getDisplayName with daylight argument 475 displayName0 = tz.getDisplayName(true, TimeZone.LONG_GENERIC, locale); 476 } 477 if (!displayName1.equals(displayName0)) { 478 errln(locale.getDisplayName() + ", " + tz.getID() + 479 ": expected " + displayName1 + " but got: " + displayName0); 480 } 481 } 482 } 483 } 484 } 485 486 public void TestGenericAPI() { 487 String id = "NewGMT"; 488 int offset = 12345; 489 490 SimpleTimeZone zone = new SimpleTimeZone(offset, id); 491 if (zone.useDaylightTime()) errln("FAIL: useDaylightTime should return false"); 492 493 TimeZone zoneclone = (TimeZone)zone.clone(); 494 if (!zoneclone.equals(zone)) errln("FAIL: clone or operator== failed"); 495 zoneclone.setID("abc"); 496 if (zoneclone.equals(zone)) errln("FAIL: clone or operator!= failed"); 497 // delete zoneclone; 498 499 zoneclone = (TimeZone)zone.clone(); 500 if (!zoneclone.equals(zone)) errln("FAIL: clone or operator== failed"); 501 zoneclone.setRawOffset(45678); 502 if (zoneclone.equals(zone)) errln("FAIL: clone or operator!= failed"); 503 504 // C++ only 505 /* 506 SimpleTimeZone copy(*zone); 507 if (!(copy == *zone)) errln("FAIL: copy constructor or operator== failed"); 508 copy = *(SimpleTimeZone*)zoneclone; 509 if (!(copy == *zoneclone)) errln("FAIL: assignment operator or operator== failed"); 510 */ 511 512 TimeZone saveDefault = TimeZone.getDefault(); 513 TimeZone.setDefault(zone); 514 TimeZone defaultzone = TimeZone.getDefault(); 515 if (defaultzone == zone) errln("FAIL: Default object is identical, not clone"); 516 if (!defaultzone.equals(zone)) errln("FAIL: Default object is not equal"); 517 TimeZone.setDefault(saveDefault); 518 // delete defaultzone; 519 // delete zoneclone; 520 521 // // ICU 2.6 Coverage 522 // logln(zone.toString()); 523 // logln(zone.getDisplayName()); 524 // SimpleTimeZoneAdapter stza = new SimpleTimeZoneAdapter((SimpleTimeZone) TimeZone.getTimeZone("GMT")); 525 // stza.setID("Foo"); 526 // if (stza.hasSameRules(java.util.TimeZone.getTimeZone("GMT"))) { 527 // errln("FAIL: SimpleTimeZoneAdapter.hasSameRules"); 528 // } 529 // stza.setRawOffset(3000); 530 // offset = stza.getOffset(GregorianCalendar.BC, 2001, Calendar.DECEMBER, 531 // 25, Calendar.TUESDAY, 12*60*60*1000); 532 // if (offset != 3000) { 533 // errln("FAIL: SimpleTimeZoneAdapter.getOffset"); 534 // } 535 // SimpleTimeZoneAdapter dup = (SimpleTimeZoneAdapter) stza.clone(); 536 // if (stza.hashCode() != dup.hashCode()) { 537 // errln("FAIL: SimpleTimeZoneAdapter.hashCode"); 538 // } 539 // if (!stza.equals(dup)) { 540 // errln("FAIL: SimpleTimeZoneAdapter.equals"); 541 // } 542 // logln(stza.toString()); 543 544 String tzver = TimeZone.getTZDataVersion(); 545 if (tzver.length() != 5 /* 4 digits + 1 letter */) { 546 errln("FAIL: getTZDataVersion returned " + tzver); 547 } else { 548 logln("PASS: tzdata version: " + tzver); 549 } 550 } 551 552 public void TestRuleAPI() 553 { 554 // ErrorCode status = ZERO_ERROR; 555 556 int offset = (int)(60*60*1000*1.75); // Pick a weird offset 557 SimpleTimeZone zone = new SimpleTimeZone(offset, "TestZone"); 558 if (zone.useDaylightTime()) errln("FAIL: useDaylightTime should return false"); 559 560 // Establish our expected transition times. Do this with a non-DST 561 // calendar with the (above) declared local offset. 562 GregorianCalendar gc = new GregorianCalendar(zone); 563 gc.clear(); 564 gc.set(1990, Calendar.MARCH, 1); 565 long marchOneStd = gc.getTime().getTime(); // Local Std time midnight 566 gc.clear(); 567 gc.set(1990, Calendar.JULY, 1); 568 long julyOneStd = gc.getTime().getTime(); // Local Std time midnight 569 570 // Starting and ending hours, WALL TIME 571 int startHour = (int)(2.25 * 3600000); 572 int endHour = (int)(3.5 * 3600000); 573 574 zone.setStartRule(Calendar.MARCH, 1, 0, startHour); 575 zone.setEndRule (Calendar.JULY, 1, 0, endHour); 576 577 gc = new GregorianCalendar(zone); 578 // if (failure(status, "new GregorianCalendar")) return; 579 580 long marchOne = marchOneStd + startHour; 581 long julyOne = julyOneStd + endHour - 3600000; // Adjust from wall to Std time 582 583 long expMarchOne = 636251400000L; 584 if (marchOne != expMarchOne) 585 { 586 errln("FAIL: Expected start computed as " + marchOne + 587 " = " + new Date(marchOne)); 588 logln(" Should be " + expMarchOne + 589 " = " + new Date(expMarchOne)); 590 } 591 592 long expJulyOne = 646793100000L; 593 if (julyOne != expJulyOne) 594 { 595 errln("FAIL: Expected start computed as " + julyOne + 596 " = " + new Date(julyOne)); 597 logln(" Should be " + expJulyOne + 598 " = " + new Date(expJulyOne)); 599 } 600 601 Calendar cal1 = Calendar.getInstance(); 602 cal1.set(1990, Calendar.JANUARY, 1); 603 Calendar cal2 = Calendar.getInstance(); 604 cal2.set(1990, Calendar.JUNE, 1); 605 _testUsingBinarySearch(zone, cal1.getTimeInMillis(), 606 cal2.getTimeInMillis(), marchOne); 607 cal1.set(1990, Calendar.JUNE, 1); 608 cal2.set(1990, Calendar.DECEMBER, 31); 609 _testUsingBinarySearch(zone, cal1.getTimeInMillis(), 610 cal2.getTimeInMillis(), julyOne); 611 612 if (zone.inDaylightTime(new Date(marchOne - 1000)) || 613 !zone.inDaylightTime(new Date(marchOne))) 614 errln("FAIL: Start rule broken"); 615 if (!zone.inDaylightTime(new Date(julyOne - 1000)) || 616 zone.inDaylightTime(new Date(julyOne))) 617 errln("FAIL: End rule broken"); 618 619 zone.setStartYear(1991); 620 if (zone.inDaylightTime(new Date(marchOne)) || 621 zone.inDaylightTime(new Date(julyOne - 1000))) 622 errln("FAIL: Start year broken"); 623 624 // failure(status, "TestRuleAPI"); 625 // delete gc; 626 // delete zone; 627 } 628 629 void _testUsingBinarySearch(SimpleTimeZone tz, long min, long max, long expectedBoundary) 630 { 631 // ErrorCode status = ZERO_ERROR; 632 boolean startsInDST = tz.inDaylightTime(new Date(min)); 633 // if (failure(status, "SimpleTimeZone::inDaylightTime")) return; 634 if (tz.inDaylightTime(new Date(max)) == startsInDST) { 635 logln("Error: inDaylightTime(" + new Date(max) + ") != " + (!startsInDST)); 636 return; 637 } 638 // if (failure(status, "SimpleTimeZone::inDaylightTime")) return; 639 while ((max - min) > INTERVAL) { 640 long mid = (min + max) / 2; 641 if (tz.inDaylightTime(new Date(mid)) == startsInDST) { 642 min = mid; 643 } 644 else { 645 max = mid; 646 } 647 // if (failure(status, "SimpleTimeZone::inDaylightTime")) return; 648 } 649 logln("Binary Search Before: " + min + " = " + new Date(min)); 650 logln("Binary Search After: " + max + " = " + new Date(max)); 651 long mindelta = expectedBoundary - min; 652 // not used long maxdelta = max - expectedBoundary; 653 if (mindelta >= 0 && 654 mindelta <= INTERVAL && 655 mindelta >= 0 && 656 mindelta <= INTERVAL) 657 logln("PASS: Expected bdry: " + expectedBoundary + " = " + new Date(expectedBoundary)); 658 else 659 errln("FAIL: Expected bdry: " + expectedBoundary + " = " + new Date(expectedBoundary)); 660 } 661 662 static final int INTERVAL = 100; 663 664 // Bug 006; verify the offset for a specific zone. 665 public void TestPRTOffset() 666 { 667 TimeZone tz = TimeZone.getTimeZone( "PRT" ); 668 if( tz == null ) { 669 errln( "FAIL: TimeZone(PRT) is null" ); 670 } 671 else{ 672 if (tz.getRawOffset() != (-4*millisPerHour)) 673 warnln("FAIL: Offset for PRT should be -4, got " + 674 tz.getRawOffset() / (double)millisPerHour); 675 } 676 677 } 678 679 // Test various calls 680 public void TestVariousAPI518() 681 { 682 TimeZone time_zone = TimeZone.getTimeZone("PST"); 683 Calendar cal = Calendar.getInstance(); 684 cal.set(1997, Calendar.APRIL, 30); 685 Date d = cal.getTime(); 686 687 logln("The timezone is " + time_zone.getID()); 688 689 if (time_zone.inDaylightTime(d) != true) 690 errln("FAIL: inDaylightTime returned false"); 691 692 if (time_zone.useDaylightTime() != true) 693 errln("FAIL: useDaylightTime returned false"); 694 695 if (time_zone.getRawOffset() != -8*millisPerHour) 696 errln( "FAIL: getRawOffset returned wrong value"); 697 698 GregorianCalendar gc = new GregorianCalendar(); 699 gc.setTime(d); 700 if (time_zone.getOffset(GregorianCalendar.AD, gc.get(GregorianCalendar.YEAR), gc.get(GregorianCalendar.MONTH), 701 gc.get(GregorianCalendar.DAY_OF_MONTH), 702 gc.get(GregorianCalendar.DAY_OF_WEEK), 0) 703 != -7*millisPerHour) 704 errln("FAIL: getOffset returned wrong value"); 705 } 706 707 // Test getAvailableID API 708 public void TestGetAvailableIDs913() 709 { 710 StringBuffer buf = new StringBuffer("TimeZone.getAvailableIDs() = { "); 711 String[] s = TimeZone.getAvailableIDs(); 712 for (int i=0; i<s.length; ++i) 713 { 714 if (i > 0) buf.append(", "); 715 buf.append(s[i]); 716 } 717 buf.append(" };"); 718 logln(buf.toString()); 719 720 buf.setLength(0); 721 buf.append("TimeZone.getAvailableIDs(GMT+02:00) = { "); 722 s = TimeZone.getAvailableIDs(+2 * 60 * 60 * 1000); 723 for (int i=0; i<s.length; ++i) 724 { 725 if (i > 0) buf.append(", "); 726 buf.append(s[i]); 727 } 728 buf.append(" };"); 729 logln(buf.toString()); 730 731 TimeZone tz = TimeZone.getTimeZone("PST"); 732 if (tz != null) 733 logln("getTimeZone(PST) = " + tz.getID()); 734 else 735 errln("FAIL: getTimeZone(PST) = null"); 736 737 tz = TimeZone.getTimeZone("America/Los_Angeles"); 738 if (tz != null) 739 logln("getTimeZone(America/Los_Angeles) = " + tz.getID()); 740 else 741 errln("FAIL: getTimeZone(PST) = null"); 742 743 // Bug 4096694 744 tz = TimeZone.getTimeZone("NON_EXISTENT"); 745 if (tz == null) 746 errln("FAIL: getTimeZone(NON_EXISTENT) = null"); 747 else if (!tz.getID().equals(TimeZone.UNKNOWN_ZONE_ID)) 748 errln("FAIL: getTimeZone(NON_EXISTENT) = " + tz.getID()); 749 } 750 751 public void TestGetAvailableIDsNew() { 752 Set<String> any = TimeZone.getAvailableIDs(SystemTimeZoneType.ANY, null, null); 753 Set<String> canonical = TimeZone.getAvailableIDs(SystemTimeZoneType.CANONICAL, null, null); 754 Set<String> canonicalLoc = TimeZone.getAvailableIDs(SystemTimeZoneType.CANONICAL_LOCATION, null, null); 755 756 checkContainsAll(any, "ANY", canonical, "CANONICAL"); 757 checkContainsAll(canonical, "CANONICAL", canonicalLoc, "CANONICALLOC"); 758 759 Set<String> any_US = TimeZone.getAvailableIDs(SystemTimeZoneType.ANY, "US", null); 760 Set<String> canonical_US = TimeZone.getAvailableIDs(SystemTimeZoneType.CANONICAL, "US", null); 761 Set<String> canonicalLoc_US = TimeZone.getAvailableIDs(SystemTimeZoneType.CANONICAL_LOCATION, "US", null); 762 763 checkContainsAll(any, "ANY", any_US, "ANY_US"); 764 checkContainsAll(canonical, "CANONICAL", canonical_US, "CANONICAL_US"); 765 checkContainsAll(canonicalLoc, "CANONICALLOC", canonicalLoc_US, "CANONICALLOC_US"); 766 767 checkContainsAll(any_US, "ANY_US", canonical_US, "CANONICAL_US"); 768 checkContainsAll(canonical_US, "CANONICAL_US", canonicalLoc_US, "CANONICALLOC_US"); 769 770 final int HOUR = 60*60*1000; 771 Set<String> any_W5 = TimeZone.getAvailableIDs(SystemTimeZoneType.ANY, null, -5 * HOUR); 772 Set<String> any_CA_W5 = TimeZone.getAvailableIDs(SystemTimeZoneType.ANY, "CA", -5 * HOUR); 773 774 checkContainsAll(any, "ANY", any_W5, "ANY_W5"); 775 checkContainsAll(any_W5, "ANY_W5", any_CA_W5, "ANY_CA_W5"); 776 777 boolean[] isSystemID = new boolean[1]; 778 779 // An ID in any set, but not in canonical set must not be a canonical ID 780 for (String id : any) { 781 if (canonical.contains(id)) { 782 continue; 783 } 784 String cid = TimeZone.getCanonicalID(id, isSystemID); 785 if (id.equals(cid)) { 786 errln("FAIL: canonical ID [" + id + "] is not in CANONICAL"); 787 } 788 if (!isSystemID[0]) { 789 errln("FAIL: ANY contains non-system ID: " + id); 790 } 791 } 792 793 // canonical set must contains only canonical IDs 794 for (String id : canonical) { 795 String cid = TimeZone.getCanonicalID(id, isSystemID); 796 if (!id.equals(cid)) { 797 errln("FAIL: CANONICAL contains non-canonical ID: " + id); 798 } 799 if (!isSystemID[0]) { 800 errln("FAIL: CANONICAL contains non-system ID: " + id); 801 } 802 } 803 804 // canonicalLoc set must contains only canonical location IDs 805 for (String id : canonicalLoc) { 806 String cid = TimeZone.getCanonicalID(id, isSystemID); 807 if (!id.equals(cid)) { 808 errln("FAIL: CANONICAL contains non-canonical ID: " + id); 809 } 810 if (!isSystemID[0]) { 811 errln("FAIL: CANONICAL contains non-system ID: " + id); 812 } 813 String region = TimeZone.getRegion(id); 814 if (region.equals("001")) { 815 errln("FAIL: CANONICALLOC contains non location zone: " + id); 816 } 817 } 818 819 // any_US must contain only US zones 820 for (String id : any_US) { 821 String region = TimeZone.getRegion(id); 822 if (!region.equals("US")) { 823 errln("FAIL: ANY_US contains non-US zone ID: " + id); 824 } 825 } 826 827 // any_W5 must contain only GMT-05:00 zones 828 for (String id : any_W5) { 829 TimeZone tz = TimeZone.getTimeZone(id); 830 if (tz.getRawOffset() != -5 * HOUR) { 831 errln("FAIL: ANY_W5 contains a zone whose offset is not -5:00: " + id); 832 } 833 } 834 835 // No US zones with GMT+14:00 836 Set<String> any_US_E14 = TimeZone.getAvailableIDs(SystemTimeZoneType.ANY, "US", 14 * HOUR); 837 if (!any_US_E14.isEmpty()) { 838 errln("FAIL: ANY_US_E14 must be empty"); 839 } 840 } 841 842 private void checkContainsAll(Set<String> set1, String name1, Set<String> set2, String name2) { 843 if (!set1.containsAll(set2)) { 844 StringBuilder buf = new StringBuilder(); 845 for (String s : set2) { 846 if (!set1.contains(s)) { 847 if (buf.length() != 0) { 848 buf.append(","); 849 } 850 buf.append(s); 851 } 852 } 853 errln("FAIL: " + name1 + " does not contain all of " + name2 + " - missing: {" + buf + "}"); 854 } 855 } 856 857 /** 858 * Bug 4107276 859 */ 860 public void TestDSTSavings() { 861 // It might be better to find a way to integrate this test into the main TimeZone 862 // tests above, but I don't have time to figure out how to do this (or if it's 863 // even really a good idea). Let's consider that a future. --rtg 1/27/98 864 SimpleTimeZone tz = new SimpleTimeZone(-5 * millisPerHour, "dstSavingsTest", 865 Calendar.MARCH, 1, 0, 0, Calendar.SEPTEMBER, 1, 0, 0, 866 (int)(0.5 * millisPerHour)); 867 868 if (tz.getRawOffset() != -5 * millisPerHour) 869 errln("Got back a raw offset of " + (tz.getRawOffset() / millisPerHour) + 870 " hours instead of -5 hours."); 871 if (!tz.useDaylightTime()) 872 errln("Test time zone should use DST but claims it doesn't."); 873 if (tz.getDSTSavings() != 0.5 * millisPerHour) 874 errln("Set DST offset to 0.5 hour, but got back " + (tz.getDSTSavings() / 875 millisPerHour) + " hours instead."); 876 877 int offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.JANUARY, 1, 878 Calendar.THURSDAY, 10 * millisPerHour); 879 if (offset != -5 * millisPerHour) 880 errln("The offset for 10 AM, 1/1/98 should have been -5 hours, but we got " 881 + (offset / millisPerHour) + " hours."); 882 883 offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.JUNE, 1, Calendar.MONDAY, 884 10 * millisPerHour); 885 if (offset != -4.5 * millisPerHour) 886 errln("The offset for 10 AM, 6/1/98 should have been -4.5 hours, but we got " 887 + (offset / millisPerHour) + " hours."); 888 889 tz.setDSTSavings(millisPerHour); 890 offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.JANUARY, 1, 891 Calendar.THURSDAY, 10 * millisPerHour); 892 if (offset != -5 * millisPerHour) 893 errln("The offset for 10 AM, 1/1/98 should have been -5 hours, but we got " 894 + (offset / millisPerHour) + " hours."); 895 896 offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.JUNE, 1, Calendar.MONDAY, 897 10 * millisPerHour); 898 if (offset != -4 * millisPerHour) 899 errln("The offset for 10 AM, 6/1/98 (with a 1-hour DST offset) should have been -4 hours, but we got " 900 + (offset / millisPerHour) + " hours."); 901 } 902 903 /** 904 * Bug 4107570 905 */ 906 public void TestAlternateRules() { 907 // Like TestDSTSavings, this test should probably be integrated somehow with the main 908 // test at the top of this class, but I didn't have time to figure out how to do that. 909 // --rtg 1/28/98 910 911 SimpleTimeZone tz = new SimpleTimeZone(-5 * millisPerHour, "alternateRuleTest"); 912 913 // test the day-of-month API 914 tz.setStartRule(Calendar.MARCH, 10, 12 * millisPerHour); 915 tz.setEndRule(Calendar.OCTOBER, 20, 12 * millisPerHour); 916 917 int offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.MARCH, 5, 918 Calendar.THURSDAY, 10 * millisPerHour); 919 if (offset != -5 * millisPerHour) 920 errln("The offset for 10AM, 3/5/98 should have been -5 hours, but we got " 921 + (offset / millisPerHour) + " hours."); 922 923 offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.MARCH, 15, 924 Calendar.SUNDAY, 10 * millisPerHour); 925 if (offset != -4 * millisPerHour) 926 errln("The offset for 10AM, 3/15/98 should have been -4 hours, but we got " 927 + (offset / millisPerHour) + " hours."); 928 929 offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.OCTOBER, 15, 930 Calendar.THURSDAY, 10 * millisPerHour); 931 if (offset != -4 * millisPerHour) 932 errln("The offset for 10AM, 10/15/98 should have been -4 hours, but we got " 933 + (offset / millisPerHour) + " hours."); 934 935 offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.OCTOBER, 25, 936 Calendar.SUNDAY, 10 * millisPerHour); 937 if (offset != -5 * millisPerHour) 938 errln("The offset for 10AM, 10/25/98 should have been -5 hours, but we got " 939 + (offset / millisPerHour) + " hours."); 940 941 // test the day-of-week-after-day-in-month API 942 tz.setStartRule(Calendar.MARCH, 10, Calendar.FRIDAY, 12 * millisPerHour, true); 943 tz.setEndRule(Calendar.OCTOBER, 20, Calendar.FRIDAY, 12 * millisPerHour, false); 944 945 offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.MARCH, 11, 946 Calendar.WEDNESDAY, 10 * millisPerHour); 947 if (offset != -5 * millisPerHour) 948 errln("The offset for 10AM, 3/11/98 should have been -5 hours, but we got " 949 + (offset / millisPerHour) + " hours."); 950 951 offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.MARCH, 14, 952 Calendar.SATURDAY, 10 * millisPerHour); 953 if (offset != -4 * millisPerHour) 954 errln("The offset for 10AM, 3/14/98 should have been -4 hours, but we got " 955 + (offset / millisPerHour) + " hours."); 956 957 offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.OCTOBER, 15, 958 Calendar.THURSDAY, 10 * millisPerHour); 959 if (offset != -4 * millisPerHour) 960 errln("The offset for 10AM, 10/15/98 should have been -4 hours, but we got " 961 + (offset / millisPerHour) + " hours."); 962 963 offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.OCTOBER, 17, 964 Calendar.SATURDAY, 10 * millisPerHour); 965 if (offset != -5 * millisPerHour) 966 errln("The offset for 10AM, 10/17/98 should have been -5 hours, but we got " 967 + (offset / millisPerHour) + " hours."); 968 } 969 970 public void TestEquivalencyGroups() { 971 String id = "America/Los_Angeles"; 972 int n = TimeZone.countEquivalentIDs(id); 973 if (n < 2) { 974 errln("FAIL: countEquivalentIDs(" + id + ") returned " + n + 975 ", expected >= 2"); 976 } 977 for (int i=0; i<n; ++i) { 978 String s = TimeZone.getEquivalentID(id, i); 979 if (s.length() == 0) { 980 errln("FAIL: getEquivalentID(" + id + ", " + i + 981 ") returned \"" + s + "\", expected valid ID"); 982 } else { 983 logln("" + i + ":" + s); 984 } 985 } 986 987 // JB#5480 - equivalent IDs should not be empty within range 988 String[] ids = TimeZone.getAvailableIDs(); 989 for (int i = 0; i < ids.length; i++) { 990 int nEquiv = TimeZone.countEquivalentIDs(ids[i]); 991 // Each equivalent ID must not be empty 992 for (int j = 0; j < nEquiv; j++) { 993 String equivID = TimeZone.getEquivalentID(ids[i], j); 994 if (equivID.length() == 0) { 995 errln("FAIL: getEquivalentID(" + ids[i] + ", " + i + 996 ") returned \"" + equivID + "\", expected valid ID"); 997 } 998 } 999 // equivalent ID out of range must be empty 1000 String outOfRangeID = TimeZone.getEquivalentID(ids[i], nEquiv); 1001 if (outOfRangeID.length() != 0) { 1002 errln("FAIL: getEquivalentID(" + ids[i] + ", " + i + 1003 ") returned \"" + outOfRangeID + "\", expected empty string"); 1004 } 1005 } 1006 1007 // Ticket#8927 invalid system ID 1008 final String[] invaldIDs = {"GMT-05:00", "Hello World!", ""}; 1009 for (String invld : invaldIDs) { 1010 int nEquiv = TimeZone.countEquivalentIDs(invld); 1011 if (nEquiv != 0) { 1012 errln("FAIL: countEquivalentIDs(" + invld + ") returned: " + nEquiv 1013 + ", expected: 0"); 1014 } 1015 String sEquiv0 = TimeZone.getEquivalentID(invld, 0); 1016 if (sEquiv0.length() > 0) { 1017 errln("FAIL: getEquivalentID(" + invld + ", 0) returned \"" + sEquiv0 1018 + "\", expected empty string"); 1019 } 1020 } 1021 } 1022 1023 public void TestCountries() { 1024 // Make sure America/Los_Angeles is in the "US" group, and 1025 // Asia/Tokyo isn't. Vice versa for the "JP" group. 1026 1027 String[] s = TimeZone.getAvailableIDs("US"); 1028 boolean la = false, tokyo = false; 1029 String laZone = "America/Los_Angeles", tokyoZone = "Asia/Tokyo"; 1030 1031 for (int i=0; i<s.length; ++i) { 1032 if (s[i].equals(laZone)) { 1033 la = true; 1034 } 1035 if (s[i].equals(tokyoZone)) { 1036 tokyo = true; 1037 } 1038 } 1039 if (!la ) { 1040 errln("FAIL: " + laZone + " in US = " + la); 1041 } 1042 if (tokyo) { 1043 errln("FAIL: " + tokyoZone + " in US = " + tokyo); 1044 } 1045 s = TimeZone.getAvailableIDs("JP"); 1046 la = false; tokyo = false; 1047 1048 for (int i=0; i<s.length; ++i) { 1049 if (s[i].equals(laZone)) { 1050 la = true; 1051 } 1052 if (s[i].equals(tokyoZone)) { 1053 tokyo = true; 1054 } 1055 } 1056 if (la) { 1057 errln("FAIL: " + laZone + " in JP = " + la); 1058 } 1059 if (!tokyo) { 1060 errln("FAIL: " + tokyoZone + " in JP = " + tokyo); 1061 } 1062 } 1063 1064 public void TestFractionalDST() { 1065 String tzName = "Australia/Lord_Howe"; // 30 min offset 1066 java.util.TimeZone tz_java = java.util.TimeZone.getTimeZone(tzName); 1067 int dst_java = 0; 1068 try { 1069 // hack so test compiles and runs in both JDK 1.3 and JDK 1.4 1070 final Object[] args = new Object[0]; 1071 final Class[] argtypes = new Class[0]; 1072 java.lang.reflect.Method m = tz_java.getClass().getMethod("getDSTSavings", argtypes); 1073 dst_java = ((Integer) m.invoke(tz_java, args)).intValue(); 1074 if (dst_java <= 0 || dst_java >= 3600000) { // didn't get the fractional time zone we wanted 1075 errln("didn't get fractional time zone!"); 1076 } 1077 } catch (NoSuchMethodException e) { 1078 // see JDKTimeZone for the reason for this code 1079 dst_java = 3600000; 1080 } catch (IllegalAccessException e) { 1081 // see JDKTimeZone for the reason for this code 1082 errln(e.getMessage()); 1083 dst_java = 3600000; 1084 } catch (InvocationTargetException e) { 1085 // see JDKTimeZone for the reason for this code 1086 errln(e.getMessage()); 1087 dst_java = 3600000; 1088 } catch (SecurityException e) { 1089 warnln(e.getMessage()); 1090 return; 1091 } 1092 1093 com.ibm.icu.util.TimeZone tz_icu = com.ibm.icu.util.TimeZone.getTimeZone(tzName); 1094 int dst_icu = tz_icu.getDSTSavings(); 1095 1096 if (dst_java != dst_icu) { 1097 warnln("java reports dst savings of " + dst_java + 1098 " but icu reports " + dst_icu + 1099 " for tz " + tz_icu.getID()); 1100 } else { 1101 logln("both java and icu report dst savings of " + dst_java + " for tz " + tz_icu.getID()); 1102 } 1103 } 1104 1105 public void TestGetOffsetDate() { 1106 Calendar cal = Calendar.getInstance(); 1107 cal.set(1997, Calendar.JANUARY, 30); 1108 long date = cal.getTimeInMillis(); 1109 1110 TimeZone tz_icu = TimeZone.getTimeZone("America/Los_Angeles"); 1111 int offset = tz_icu.getOffset(date); 1112 if (offset != -28800000) { 1113 errln("expected offset -28800000, got: " + offset); 1114 } 1115 1116 cal.set(1997, Calendar.JULY, 30); 1117 date = cal.getTimeInMillis(); 1118 offset = tz_icu.getOffset(date); 1119 if (offset != -25200000) { 1120 errln("expected offset -25200000, got: " + offset); 1121 } 1122 } 1123 1124 // jb4484 1125 public void TestSimpleTimeZoneSerialization() 1126 { 1127 SimpleTimeZone stz0 = new SimpleTimeZone(32400000, "MyTimeZone"); 1128 SimpleTimeZone stz1 = new SimpleTimeZone(32400000, "Asia/Tokyo"); 1129 SimpleTimeZone stz2 = new SimpleTimeZone(32400000, "Asia/Tokyo"); 1130 stz2.setRawOffset(0); 1131 SimpleTimeZone stz3 = new SimpleTimeZone(32400000, "Asia/Tokyo"); 1132 stz3.setStartYear(100); 1133 SimpleTimeZone stz4 = new SimpleTimeZone(32400000, "Asia/Tokyo"); 1134 stz4.setStartYear(1000); 1135 stz4.setDSTSavings(1800000); 1136 stz4.setStartRule(3, 4, 180000); 1137 stz4.setEndRule(6, 3, 4, 360000); 1138 SimpleTimeZone stz5 = new SimpleTimeZone(32400000, "Asia/Tokyo"); 1139 stz5.setStartRule(2, 3, 4, 360000); 1140 stz5.setEndRule(6, 3, 4, 360000); 1141 1142 SimpleTimeZone[] stzs = { stz0, stz1, stz2, stz3, stz4, stz5, }; 1143 1144 for (int i = 0; i < stzs.length; ++i) { 1145 SimpleTimeZone stz = stzs[i]; 1146 try { 1147 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 1148 ObjectOutputStream oos = new ObjectOutputStream(baos); 1149 oos.writeObject(stz); 1150 oos.close(); 1151 byte[] bytes = baos.toByteArray(); 1152 logln("id: " + stz.getID() + " length: " + bytes.length); 1153 1154 ByteArrayInputStream bais = new ByteArrayInputStream(bytes); 1155 ObjectInputStream ois = new ObjectInputStream(bais); 1156 1157 SimpleTimeZone stzDeserialized = (SimpleTimeZone)ois.readObject(); 1158 ois.close(); 1159 1160 assertEquals("time zones", stz, stzDeserialized); 1161 } 1162 catch (ClassCastException cce) { 1163 cce.printStackTrace(); 1164 errln("could not deserialize SimpleTimeZone"); 1165 } 1166 catch (IOException ioe) { 1167 errln(ioe.getMessage()); 1168 } 1169 catch (ClassNotFoundException cnfe) { 1170 errln(cnfe.getMessage()); 1171 } 1172 } 1173 } 1174 1175 // jb4175 1176 /* Generated by org.unicode.cldr.tool.CountItems */ 1177 private static final String[] timeZoneTestNames = { 1178 "America/Argentina/Buenos_Aires", "America/Buenos_Aires", 1179 "America/Argentina/Catamarca", "America/Catamarca", 1180 "America/Argentina/Cordoba", "America/Cordoba", 1181 "America/Argentina/Jujuy", "America/Jujuy", 1182 "America/Argentina/Mendoza", "America/Mendoza", 1183 "America/Atka", "America/Adak", 1184 "America/Ensenada", "America/Tijuana", 1185 "America/Fort_Wayne", "America/Indianapolis", 1186 "America/Indiana/Indianapolis", "America/Indianapolis", 1187 "America/Kentucky/Louisville", "America/Louisville", 1188 "America/Knox_IN", "America/Indiana/Knox", 1189 "America/Porto_Acre", "America/Rio_Branco", 1190 "America/Rosario", "America/Cordoba", 1191 "America/Virgin", "America/St_Thomas", 1192 "Asia/Ashkhabad", "Asia/Ashgabat", 1193 "Asia/Chungking", "Asia/Chongqing", 1194 "Asia/Dacca", "Asia/Dhaka", 1195 "Asia/Istanbul", "Europe/Istanbul", 1196 "Asia/Macao", "Asia/Macau", 1197 "Asia/Tel_Aviv", "Asia/Jerusalem", 1198 "Asia/Thimbu", "Asia/Thimphu", 1199 "Asia/Ujung_Pandang", "Asia/Makassar", 1200 "Asia/Ulan_Bator", "Asia/Ulaanbaatar", 1201 "Australia/ACT", "Australia/Sydney", 1202 "Australia/Canberra", "Australia/Sydney", 1203 "Australia/LHI", "Australia/Lord_Howe", 1204 "Australia/NSW", "Australia/Sydney", 1205 "Australia/North", "Australia/Darwin", 1206 "Australia/Queensland", "Australia/Brisbane", 1207 "Australia/South", "Australia/Adelaide", 1208 "Australia/Tasmania", "Australia/Hobart", 1209 "Australia/Victoria", "Australia/Melbourne", 1210 "Australia/West", "Australia/Perth", 1211 "Australia/Yancowinna", "Australia/Broken_Hill", 1212 "Brazil/Acre", "America/Rio_Branco", 1213 "Brazil/DeNoronha", "America/Noronha", 1214 "Brazil/East", "America/Sao_Paulo", 1215 "Brazil/West", "America/Manaus", 1216 "CST6CDT", "America/Chicago", 1217 "Canada/Atlantic", "America/Halifax", 1218 "Canada/Central", "America/Winnipeg", 1219 "Canada/East-Saskatchewan", "America/Regina", 1220 "Canada/Eastern", "America/Toronto", 1221 "Canada/Mountain", "America/Edmonton", 1222 "Canada/Newfoundland", "America/St_Johns", 1223 "Canada/Pacific", "America/Vancouver", 1224 "Canada/Saskatchewan", "America/Regina", 1225 "Canada/Yukon", "America/Whitehorse", 1226 "Chile/Continental", "America/Santiago", 1227 "Chile/EasterIsland", "Pacific/Easter", 1228 "Cuba", "America/Havana", 1229 "EST", "America/Indianapolis", 1230 "EST5EDT", "America/New_York", 1231 "Egypt", "Africa/Cairo", 1232 "Eire", "Europe/Dublin", 1233 "Etc/GMT+0", "Etc/GMT", 1234 "Etc/GMT-0", "Etc/GMT", 1235 "Etc/GMT0", "Etc/GMT", 1236 "Etc/Greenwich", "Etc/GMT", 1237 "Etc/UCT", "Etc/GMT", 1238 "Etc/UTC", "Etc/GMT", 1239 "Etc/Universal", "Etc/GMT", 1240 "Etc/Zulu", "Etc/GMT", 1241 "Europe/Nicosia", "Asia/Nicosia", 1242 "Europe/Tiraspol", "Europe/Chisinau", 1243 "GB", "Europe/London", 1244 "GB-Eire", "Europe/London", 1245 "GMT", "Etc/GMT", 1246 "GMT+0", "Etc/GMT", 1247 "GMT-0", "Etc/GMT", 1248 "GMT0", "Etc/GMT", 1249 "Greenwich", "Etc/GMT", 1250 "HST", "Pacific/Honolulu", 1251 "Hongkong", "Asia/Hong_Kong", 1252 "Iceland", "Atlantic/Reykjavik", 1253 "Iran", "Asia/Tehran", 1254 "Israel", "Asia/Jerusalem", 1255 "Jamaica", "America/Jamaica", 1256 "Japan", "Asia/Tokyo", 1257 "Kwajalein", "Pacific/Kwajalein", 1258 "Libya", "Africa/Tripoli", 1259 "MST", "America/Phoenix", 1260 "MST7MDT", "America/Denver", 1261 "Mexico/BajaNorte", "America/Tijuana", 1262 "Mexico/BajaSur", "America/Mazatlan", 1263 "Mexico/General", "America/Mexico_City", 1264 "NZ", "Pacific/Auckland", 1265 "NZ-CHAT", "Pacific/Chatham", 1266 "Navajo", "America/Shiprock", /* fixed from Mark's original */ 1267 "PRC", "Asia/Shanghai", 1268 "PST8PDT", "America/Los_Angeles", 1269 "Pacific/Samoa", "Pacific/Pago_Pago", 1270 "Poland", "Europe/Warsaw", 1271 "Portugal", "Europe/Lisbon", 1272 "ROC", "Asia/Taipei", 1273 "ROK", "Asia/Seoul", 1274 "Singapore", "Asia/Singapore", 1275 "SystemV/AST4", "America/Puerto_Rico", 1276 "SystemV/AST4ADT", "America/Halifax", 1277 "SystemV/CST6", "America/Regina", 1278 "SystemV/CST6CDT", "America/Chicago", 1279 "SystemV/EST5", "America/Indianapolis", 1280 "SystemV/EST5EDT", "America/New_York", 1281 "SystemV/HST10", "Pacific/Honolulu", 1282 "SystemV/MST7", "America/Phoenix", 1283 "SystemV/MST7MDT", "America/Denver", 1284 "SystemV/PST8", "Pacific/Pitcairn", 1285 "SystemV/PST8PDT", "America/Los_Angeles", 1286 "SystemV/YST9", "Pacific/Gambier", 1287 "SystemV/YST9YDT", "America/Anchorage", 1288 "Turkey", "Europe/Istanbul", 1289 "UCT", "Etc/GMT", 1290 "US/Alaska", "America/Anchorage", 1291 "US/Aleutian", "America/Adak", 1292 "US/Arizona", "America/Phoenix", 1293 "US/Central", "America/Chicago", 1294 "US/East-Indiana", "America/Indianapolis", 1295 "US/Eastern", "America/New_York", 1296 "US/Hawaii", "Pacific/Honolulu", 1297 "US/Indiana-Starke", "America/Indiana/Knox", 1298 "US/Michigan", "America/Detroit", 1299 "US/Mountain", "America/Denver", 1300 "US/Pacific", "America/Los_Angeles", 1301 "US/Pacific-New", "America/Los_Angeles", 1302 "US/Samoa", "Pacific/Pago_Pago", 1303 "UTC", "Etc/GMT", 1304 "Universal", "Etc/GMT", 1305 "W-SU", "Europe/Moscow", 1306 "Zulu", "Etc/GMT", 1307 }; 1308 1309 public void TestOddTimeZoneNames() { 1310 for (int i = 0; i < timeZoneTestNames.length; i += 2) { 1311 String funkyName = timeZoneTestNames[i]; 1312 String correctName = timeZoneTestNames[i+1]; 1313 1314 TimeZone ftz = TimeZone.getTimeZone(funkyName); 1315 TimeZone ctz = TimeZone.getTimeZone(correctName); 1316 1317 String fdn = ftz.getDisplayName(); 1318 long fro = ftz.getRawOffset(); 1319 long fds = ftz.getDSTSavings(); 1320 boolean fdy = ftz.useDaylightTime(); 1321 1322 String cdn = ctz.getDisplayName(); 1323 long cro = ctz.getRawOffset(); 1324 long cds = ctz.getDSTSavings(); 1325 boolean cdy = ctz.useDaylightTime(); 1326 1327 if (!fdn.equals(cdn)) { 1328 logln("display name (" + funkyName + ", " + correctName + ") expected: " + cdn + " but got: " + fdn); 1329 } else if (fro != cro) { 1330 logln("offset (" + funkyName + ", " + correctName + ") expected: " + cro + " but got: " + fro); 1331 } else if (fds != cds) { 1332 logln("daylight (" + funkyName + ", " + correctName + ") expected: " + cds + " but got: " + fds); 1333 } else if (fdy != cdy) { 1334 logln("uses daylight (" + funkyName + ", " + correctName + ") expected: " + cdy + " but got: " + fdy); 1335 } else { 1336 // no error, assume we're referencing the same internal java object 1337 } 1338 } 1339 } 1340 1341 public void TestCoverage(){ 1342 class StubTimeZone extends TimeZone{ 1343 /** 1344 * For serialization 1345 */ 1346 private static final long serialVersionUID = 8658654217433379343L; 1347 public int getOffset(int era, int year, int month, int day, int dayOfWeek, int milliseconds) {return 0;} 1348 public void setRawOffset(int offsetMillis) {} 1349 public int getRawOffset() {return 0;} 1350 public boolean useDaylightTime() {return false;} 1351 public boolean inDaylightTime(Date date) {return false;} 1352 } 1353 StubTimeZone stub = new StubTimeZone(); 1354 StubTimeZone stub2 = (StubTimeZone) stub.clone(); 1355 if (stub.getDSTSavings() != 0){ 1356 errln("TimeZone.getDSTSavings() should return 0"); 1357 } 1358 if (!stub.hasSameRules(stub2)){ 1359 errln("TimeZone.clone() object should hasSameRules"); 1360 1361 } 1362 } 1363 public void TestMark(){ 1364 String tzid = "America/Argentina/ComodRivadavia"; 1365 TimeZone tz = TimeZone.getTimeZone(tzid); 1366 int offset = tz.getOffset(new Date().getTime()); 1367 logln(tzid + ":\t" + offset); 1368 List list = Arrays.asList(TimeZone.getAvailableIDs()); 1369 if(!list.contains(tzid)){ 1370 errln("Could create the time zone but it is not in getAvailableIDs"); 1371 } 1372 } 1373 public void TestZoneMeta() { 1374 java.util.TimeZone save = java.util.TimeZone.getDefault(); 1375 java.util.TimeZone newZone = java.util.TimeZone.getTimeZone("GMT-08:00"); 1376 com.ibm.icu.util.TimeZone.setDefault(null); 1377 java.util.TimeZone.setDefault(newZone); 1378 SimpleTimeZone zone = new SimpleTimeZone(0, "GMT"); 1379 com.ibm.icu.util.TimeZone defaultZone = com.ibm.icu.util.TimeZone.getDefault(); 1380 if(defaultZone==null){ 1381 errln("TimeZone.getDefault() failed for GMT-08:00"); 1382 } 1383 if(zone==null){ 1384 errln("SimpleTimeZone(0, GMT-08:00) failed for GMT-08:00"); 1385 } 1386 //reset 1387 java.util.TimeZone.setDefault(save); 1388 } 1389 1390 // Copied from the protected constant in TimeZone. 1391 private static final int MILLIS_PER_HOUR = 60*60*1000; 1392 1393 // Test that a transition at the end of February is handled correctly. 1394 public void TestFebruary() { 1395 // Time zone with daylight savings time from the first Sunday in November 1396 // to the last Sunday in February. 1397 // Similar to the new rule for Brazil (Sao Paulo) in tzdata2006n. 1398 // 1399 // Note: In tzdata2007h, the rule had changed, so no actual zones uses 1400 // lastSun in Feb anymore. 1401 SimpleTimeZone tz1 = new SimpleTimeZone( 1402 -3 * MILLIS_PER_HOUR, // raw offset: 3h before (west of) GMT 1403 "nov-feb", 1404 Calendar.NOVEMBER, 1, Calendar.SUNDAY, // start: November, first, Sunday 1405 0, // midnight wall time 1406 Calendar.FEBRUARY, -1, Calendar.SUNDAY, // end: February, last, Sunday 1407 0); // midnight wall time 1408 1409 // Now hardcode the same rules as for Brazil in tzdata 2006n, so that 1410 // we cover the intended code even when in the future zoneinfo hardcodes 1411 // these transition dates. 1412 SimpleTimeZone tz2= new SimpleTimeZone( 1413 -3 * MILLIS_PER_HOUR, // raw offset: 3h before (west of) GMT 1414 "nov-feb2", 1415 Calendar.NOVEMBER, 1, -Calendar.SUNDAY, // start: November, 1 or after, Sunday 1416 0, // midnight wall time 1417 Calendar.FEBRUARY, -29, -Calendar.SUNDAY,// end: February, 29 or before, Sunday 1418 0); // midnight wall time 1419 1420 // Gregorian calendar with the UTC time zone for getting sample test date/times. 1421 GregorianCalendar gc = new GregorianCalendar(TimeZone.getTimeZone("Etc/GMT")); 1422 // "Unable to create the UTC calendar: %s" 1423 1424 int[] data = { 1425 // UTC time (6 fields) followed by 1426 // expected time zone offset in hours after GMT (negative=before GMT). 1427 // int year, month, day, hour, minute, second, offsetHours 1428 2006, Calendar.NOVEMBER, 5, 02, 59, 59, -3, 1429 2006, Calendar.NOVEMBER, 5, 03, 00, 00, -2, 1430 2007, Calendar.FEBRUARY, 25, 01, 59, 59, -2, 1431 2007, Calendar.FEBRUARY, 25, 02, 00, 00, -3, 1432 1433 2007, Calendar.NOVEMBER, 4, 02, 59, 59, -3, 1434 2007, Calendar.NOVEMBER, 4, 03, 00, 00, -2, 1435 2008, Calendar.FEBRUARY, 24, 01, 59, 59, -2, 1436 2008, Calendar.FEBRUARY, 24, 02, 00, 00, -3, 1437 1438 2008, Calendar.NOVEMBER, 2, 02, 59, 59, -3, 1439 2008, Calendar.NOVEMBER, 2, 03, 00, 00, -2, 1440 2009, Calendar.FEBRUARY, 22, 01, 59, 59, -2, 1441 2009, Calendar.FEBRUARY, 22, 02, 00, 00, -3, 1442 1443 2009, Calendar.NOVEMBER, 1, 02, 59, 59, -3, 1444 2009, Calendar.NOVEMBER, 1, 03, 00, 00, -2, 1445 2010, Calendar.FEBRUARY, 28, 01, 59, 59, -2, 1446 2010, Calendar.FEBRUARY, 28, 02, 00, 00, -3 1447 }; 1448 1449 TimeZone timezones[] = { tz1, tz2 }; 1450 1451 TimeZone tz; 1452 Date dt; 1453 int t, i, raw, dst; 1454 int[] offsets = new int[2]; // raw = offsets[0], dst = offsets[1] 1455 for (t = 0; t < timezones.length; ++t) { 1456 tz = timezones[t]; 1457 for (i = 0; i < data.length; i+=7) { 1458 gc.set(data[i], data[i+1], data[i+2], 1459 data[i+3], data[i+4], data[i+5]); 1460 dt = gc.getTime(); 1461 tz.getOffset(dt.getTime(), false, offsets); 1462 raw = offsets[0]; 1463 dst = offsets[1]; 1464 if ((raw + dst) != data[i+6] * MILLIS_PER_HOUR) { 1465 errln("test case " + t + "." + (i/7) + ": " + 1466 "tz.getOffset(" + data[i] + "-" + (data[i+1] + 1) + "-" + data[i+2] + " " + 1467 data[i+3] + ":" + data[i+4] + ":" + data[i+5] + 1468 ") returns " + raw + "+" + dst + " != " + data[i+6] * MILLIS_PER_HOUR); 1469 } 1470 } 1471 } 1472 } 1473 1474 public void TestCanonicalID() { 1475 // Some canonical IDs in CLDR are defined as "Link" 1476 // in Olson tzdata. 1477 final String[][] excluded1 = { 1478 {"Africa/Addis_Ababa", "Africa/Nairobi"}, 1479 {"Africa/Asmera", "Africa/Nairobi"}, 1480 {"Africa/Bamako", "Africa/Abidjan"}, 1481 {"Africa/Bangui", "Africa/Lagos"}, 1482 {"Africa/Banjul", "Africa/Abidjan"}, 1483 {"Africa/Blantyre", "Africa/Maputo"}, 1484 {"Africa/Brazzaville", "Africa/Lagos"}, 1485 {"Africa/Bujumbura", "Africa/Maputo"}, 1486 {"Africa/Conakry", "Africa/Abidjan"}, 1487 {"Africa/Dakar", "Africa/Abidjan"}, 1488 {"Africa/Dar_es_Salaam", "Africa/Nairobi"}, 1489 {"Africa/Djibouti", "Africa/Nairobi"}, 1490 {"Africa/Douala", "Africa/Lagos"}, 1491 {"Africa/Freetown", "Africa/Abidjan"}, 1492 {"Africa/Gaborone", "Africa/Maputo"}, 1493 {"Africa/Harare", "Africa/Maputo"}, 1494 {"Africa/Kampala", "Africa/Nairobi"}, 1495 {"Africa/Khartoum", "Africa/Juba"}, 1496 {"Africa/Kigali", "Africa/Maputo"}, 1497 {"Africa/Kinshasa", "Africa/Lagos"}, 1498 {"Africa/Libreville", "Africa/Lagos"}, 1499 {"Africa/Lome", "Africa/Abidjan"}, 1500 {"Africa/Luanda", "Africa/Lagos"}, 1501 {"Africa/Lubumbashi", "Africa/Maputo"}, 1502 {"Africa/Lusaka", "Africa/Maputo"}, 1503 {"Africa/Maseru", "Africa/Johannesburg"}, 1504 {"Africa/Malabo", "Africa/Lagos"}, 1505 {"Africa/Mbabane", "Africa/Johannesburg"}, 1506 {"Africa/Mogadishu", "Africa/Nairobi"}, 1507 {"Africa/Niamey", "Africa/Lagos"}, 1508 {"Africa/Nouakchott", "Africa/Abidjan"}, 1509 {"Africa/Ouagadougou", "Africa/Abidjan"}, 1510 {"Africa/Porto-Novo", "Africa/Lagos"}, 1511 {"Africa/Sao_Tome", "Africa/Abidjan"}, 1512 {"America/Antigua", "America/Port_of_Spain"}, 1513 {"America/Anguilla", "America/Port_of_Spain"}, 1514 {"America/Curacao", "America/Aruba"}, 1515 {"America/Dominica", "America/Port_of_Spain"}, 1516 {"America/Grenada", "America/Port_of_Spain"}, 1517 {"America/Guadeloupe", "America/Port_of_Spain"}, 1518 {"America/Kralendijk", "America/Aruba"}, 1519 {"America/Lower_Princes", "America/Aruba"}, 1520 {"America/Marigot", "America/Port_of_Spain"}, 1521 {"America/Montserrat", "America/Port_of_Spain"}, 1522 {"America/Panama", "America/Cayman"}, 1523 {"America/Shiprock", "America/Denver"}, 1524 {"America/St_Barthelemy", "America/Port_of_Spain"}, 1525 {"America/St_Kitts", "America/Port_of_Spain"}, 1526 {"America/St_Lucia", "America/Port_of_Spain"}, 1527 {"America/St_Thomas", "America/Port_of_Spain"}, 1528 {"America/St_Vincent", "America/Port_of_Spain"}, 1529 {"America/Toronto", "America/Montreal"}, 1530 {"America/Tortola", "America/Port_of_Spain"}, 1531 {"America/Virgin", "America/Port_of_Spain"}, 1532 {"Antarctica/South_Pole", "Antarctica/McMurdo"}, 1533 {"Arctic/Longyearbyen", "Europe/Oslo"}, 1534 {"Asia/Kuwait", "Asia/Aden"}, 1535 {"Asia/Muscat", "Asia/Dubai"}, 1536 {"Asia/Phnom_Penh", "Asia/Bangkok"}, 1537 {"Asia/Qatar", "Asia/Bahrain"}, 1538 {"Asia/Riyadh", "Asia/Aden"}, 1539 {"Asia/Vientiane", "Asia/Bangkok"}, 1540 {"Atlantic/Jan_Mayen", "Europe/Oslo"}, 1541 {"Atlantic/St_Helena", "Africa/Abidjan"}, 1542 {"Europe/Bratislava", "Europe/Prague"}, 1543 {"Europe/Busingen", "Europe/Zurich"}, 1544 {"Europe/Guernsey", "Europe/London"}, 1545 {"Europe/Isle_of_Man", "Europe/London"}, 1546 {"Europe/Jersey", "Europe/London"}, 1547 {"Europe/Ljubljana", "Europe/Belgrade"}, 1548 {"Europe/Mariehamn", "Europe/Helsinki"}, 1549 {"Europe/Podgorica", "Europe/Belgrade"}, 1550 {"Europe/San_Marino", "Europe/Rome"}, 1551 {"Europe/Sarajevo", "Europe/Belgrade"}, 1552 {"Europe/Skopje", "Europe/Belgrade"}, 1553 {"Europe/Vaduz", "Europe/Zurich"}, 1554 {"Europe/Vatican", "Europe/Rome"}, 1555 {"Europe/Zagreb", "Europe/Belgrade"}, 1556 {"Indian/Antananarivo", "Africa/Nairobi"}, 1557 {"Indian/Comoro", "Africa/Nairobi"}, 1558 {"Indian/Mayotte", "Africa/Nairobi"}, 1559 {"Pacific/Auckland", "Antarctica/McMurdo"}, 1560 {"Pacific/Johnston", "Pacific/Honolulu"}, 1561 {"Pacific/Midway", "Pacific/Pago_Pago"}, 1562 {"Pacific/Saipan", "Pacific/Guam"}, 1563 }; 1564 1565 // Following IDs are aliases of Etc/GMT in CLDR, 1566 // but Olson tzdata has 3 independent definitions 1567 // for Etc/GMT, Etc/UTC, Etc/UCT. 1568 // Until we merge them into one equivalent group 1569 // in zoneinfo.res, we exclude them in the test 1570 // below. 1571 final String[] excluded2 = { 1572 "Etc/UCT", "UCT", 1573 "Etc/UTC", "UTC", 1574 "Etc/Universal", "Universal", 1575 "Etc/Zulu", "Zulu", 1576 }; 1577 1578 // Walk through equivalency groups 1579 String[] ids = TimeZone.getAvailableIDs(); 1580 for (int i = 0; i < ids.length; i++) { 1581 int nEquiv = TimeZone.countEquivalentIDs(ids[i]); 1582 if (nEquiv == 0) { 1583 continue; 1584 } 1585 String canonicalID = null; 1586 boolean bFoundCanonical = false; 1587 // Make sure getCanonicalID returns the exact same result 1588 // for all entries within a same equivalency group with some 1589 // exceptions listed in exluded1. 1590 // Also, one of them must be canonical id. 1591 for (int j = 0; j < nEquiv; j++) { 1592 String tmp = TimeZone.getEquivalentID(ids[i], j); 1593 String tmpCanonical = TimeZone.getCanonicalID(tmp); 1594 if (tmpCanonical == null) { 1595 errln("FAIL: getCanonicalID(\"" + tmp + "\") returned null"); 1596 continue; 1597 } 1598 // Some exceptional cases 1599 for (int k = 0; k < excluded1.length; k++) { 1600 if (tmpCanonical.equals(excluded1[k][0])) { 1601 tmpCanonical = excluded1[k][1]; 1602 } 1603 } 1604 1605 if (j == 0) { 1606 canonicalID = tmpCanonical; 1607 } else if (!canonicalID.equals(tmpCanonical)) { 1608 errln("FAIL: getCanonicalID(\"" + tmp + "\") returned " + tmpCanonical + " expected:" + canonicalID); 1609 } 1610 1611 if (canonicalID.equals(tmp)) { 1612 bFoundCanonical = true; 1613 } 1614 } 1615 // At least one ID in an equvalency group must match the 1616 // canonicalID 1617 if (!bFoundCanonical) { 1618 // test exclusion because of differences between Olson tzdata and CLDR 1619 boolean isExcluded = false; 1620 for (int k = 0; k < excluded1.length; k++) { 1621 if (ids[i].equals(excluded2[k])) { 1622 isExcluded = true; 1623 break; 1624 } 1625 } 1626 if (isExcluded) { 1627 continue; 1628 } 1629 1630 errln("FAIL: No timezone ids match the canonical ID " + canonicalID); 1631 } 1632 } 1633 // Testing some special cases 1634 final String[][] data = { 1635 {"GMT-03", "GMT-03:00", null}, 1636 {"GMT+4", "GMT+04:00", null}, 1637 {"GMT-055", "GMT-00:55", null}, 1638 {"GMT+430", "GMT+04:30", null}, 1639 {"GMT-12:15", "GMT-12:15", null}, 1640 {"GMT-091015", "GMT-09:10:15", null}, 1641 {"GMT+1:90", null, null}, 1642 {"America/Argentina/Buenos_Aires", "America/Buenos_Aires", "true"}, 1643 {"Etc/Unknown", "Etc/Unknown", null}, 1644 {"bogus", null, null}, 1645 {"", null, null}, 1646 {"America/Marigot", "America/Marigot", "true"}, // Olson link, but CLDR canonical (#8953) 1647 {"Europe/Bratislava", "Europe/Bratislava", "true"}, // Same as above 1648 {null, null, null}, 1649 }; 1650 boolean[] isSystemID = new boolean[1]; 1651 for (int i = 0; i < data.length; i++) { 1652 String canonical = TimeZone.getCanonicalID(data[i][0], isSystemID); 1653 if (canonical != null && !canonical.equals(data[i][1]) 1654 || canonical == null && data[i][1] != null) { 1655 errln("FAIL: getCanonicalID(\"" + data[i][0] + "\") returned " + canonical 1656 + " - expected: " + data[i][1]); 1657 } 1658 if ("true".equalsIgnoreCase(data[i][2]) != isSystemID[0]) { 1659 errln("FAIL: getCanonicalID(\"" + data[i][0] + "\") set " + isSystemID[0] 1660 + " to isSystemID"); 1661 } 1662 } 1663 } 1664 1665 public void TestSetDefault() { 1666 java.util.TimeZone save = java.util.TimeZone.getDefault(); 1667 1668 /* 1669 * America/Caracs (Venezuela) changed the base offset from -4:00 to 1670 * -4:30 on Dec 9, 2007. 1671 */ 1672 1673 TimeZone icuCaracas = TimeZone.getTimeZone("America/Caracas", TimeZone.TIMEZONE_ICU); 1674 java.util.TimeZone jdkCaracas = java.util.TimeZone.getTimeZone("America/Caracas"); 1675 1676 // Set JDK America/Caracas as the default 1677 java.util.TimeZone.setDefault(jdkCaracas); 1678 1679 java.util.Calendar jdkCal = java.util.Calendar.getInstance(); 1680 jdkCal.clear(); 1681 jdkCal.set(2007, java.util.Calendar.JANUARY, 1); 1682 1683 int rawOffset = jdkCal.get(java.util.Calendar.ZONE_OFFSET); 1684 int dstSavings = jdkCal.get(java.util.Calendar.DST_OFFSET); 1685 1686 int[] offsets = new int[2]; 1687 icuCaracas.getOffset(jdkCal.getTime().getTime()/*jdkCal.getTimeInMillis()*/, false, offsets); 1688 1689 boolean isTimeZoneSynchronized = true; 1690 1691 if (rawOffset != offsets[0] || dstSavings != offsets[1]) { 1692 // JDK time zone rule is out of sync... 1693 logln("Rule for JDK America/Caracas is not same with ICU. Skipping the rest."); 1694 isTimeZoneSynchronized = false; 1695 } 1696 1697 if (isTimeZoneSynchronized) { 1698 // If JDK America/Caracas uses the same rule with ICU, 1699 // the following code should work well. 1700 TimeZone.setDefault(icuCaracas); 1701 1702 // Create a new JDK calendar instance again. 1703 // This calendar should reflect the new default 1704 // set by ICU TimeZone#setDefault. 1705 jdkCal = java.util.Calendar.getInstance(); 1706 jdkCal.clear(); 1707 jdkCal.set(2007, java.util.Calendar.JANUARY, 1); 1708 1709 rawOffset = jdkCal.get(java.util.Calendar.ZONE_OFFSET); 1710 dstSavings = jdkCal.get(java.util.Calendar.DST_OFFSET); 1711 1712 if (rawOffset != offsets[0] || dstSavings != offsets[1]) { 1713 errln("ERROR: Got offset [raw:" + rawOffset + "/dst:" + dstSavings 1714 + "] Expected [raw:" + offsets[0] + "/dst:" + offsets[1] + "]"); 1715 } 1716 } 1717 1718 // Restore the original JDK time zone 1719 java.util.TimeZone.setDefault(save); 1720 } 1721 1722 /* 1723 * Test Display Names, choosing zones and lcoales where there are multiple 1724 * meta-zones defined. 1725 */ 1726 public void TestDisplayNamesMeta() { 1727 final Integer TZSHORT = new Integer(TimeZone.SHORT); 1728 final Integer TZLONG = new Integer(TimeZone.LONG); 1729 1730 final Object[][] zoneDisplayTestData = { 1731 // zone id locale summer format expected display name 1732 {"Europe/London", "en", Boolean.FALSE, TZSHORT, "GMT"}, 1733 {"Europe/London", "en", Boolean.FALSE, TZLONG, "Greenwich Mean Time"}, 1734 {"Europe/London", "en", Boolean.TRUE, TZSHORT, "GMT+1" /*"BST"*/}, 1735 {"Europe/London", "en", Boolean.TRUE, TZLONG, "British Summer Time"}, 1736 1737 {"America/Anchorage", "en", Boolean.FALSE, TZSHORT, "AKST"}, 1738 {"America/Anchorage", "en", Boolean.FALSE, TZLONG, "Alaska Standard Time"}, 1739 {"America/Anchorage", "en", Boolean.TRUE, TZSHORT, "AKDT"}, 1740 {"America/Anchorage", "en", Boolean.TRUE, TZLONG, "Alaska Daylight Time"}, 1741 1742 // Southern Hemisphere, all data from meta:Australia_Western 1743 {"Australia/Perth", "en", Boolean.FALSE, TZSHORT, "GMT+8"/*"AWST"*/}, 1744 {"Australia/Perth", "en", Boolean.FALSE, TZLONG, "Australian Western Standard Time"}, 1745 // Note: Perth does not observe DST currently. When display name is missing, 1746 // the localized GMT format with the current offset is used even daylight name was 1747 // requested. See #9350. 1748 {"Australia/Perth", "en", Boolean.TRUE, TZSHORT, "GMT+8"/*"AWDT"*/}, 1749 {"Australia/Perth", "en", Boolean.TRUE, TZLONG, "Australian Western Daylight Time"}, 1750 1751 {"America/Sao_Paulo", "en", Boolean.FALSE, TZSHORT, "GMT-3"/*"BRT"*/}, 1752 {"America/Sao_Paulo", "en", Boolean.FALSE, TZLONG, "Brasilia Standard Time"}, 1753 {"America/Sao_Paulo", "en", Boolean.TRUE, TZSHORT, "GMT-2"/*"BRST"*/}, 1754 {"America/Sao_Paulo", "en", Boolean.TRUE, TZLONG, "Brasilia Summer Time"}, 1755 1756 // No Summer Time, but had it before 1983. 1757 {"Pacific/Honolulu", "en", Boolean.FALSE, TZSHORT, "HST"}, 1758 {"Pacific/Honolulu", "en", Boolean.FALSE, TZLONG, "Hawaii-Aleutian Standard Time"}, 1759 {"Pacific/Honolulu", "en", Boolean.TRUE, TZSHORT, "HDT"}, 1760 {"Pacific/Honolulu", "en", Boolean.TRUE, TZLONG, "Hawaii-Aleutian Daylight Time"}, 1761 1762 // Northern, has Summer, not commonly used. 1763 {"Europe/Helsinki", "en", Boolean.FALSE, TZSHORT, "GMT+2"/*"EET"*/}, 1764 {"Europe/Helsinki", "en", Boolean.FALSE, TZLONG, "Eastern European Standard Time"}, 1765 {"Europe/Helsinki", "en", Boolean.TRUE, TZSHORT, "GMT+3"/*"EEST"*/}, 1766 {"Europe/Helsinki", "en", Boolean.TRUE, TZLONG, "Eastern European Summer Time"}, 1767 1768 // Repeating the test data for DST. The test data below trigger the problem reported 1769 // by Ticket#6644 1770 {"Europe/London", "en", Boolean.TRUE, TZSHORT, "GMT+1" /*"BST"*/}, 1771 {"Europe/London", "en", Boolean.TRUE, TZLONG, "British Summer Time"}, 1772 }; 1773 1774 boolean isICUTimeZone = (TimeZone.getDefaultTimeZoneType() == TimeZone.TIMEZONE_ICU); 1775 1776 boolean sawAnError = false; 1777 for (int testNum = 0; testNum < zoneDisplayTestData.length; testNum++) { 1778 ULocale locale = new ULocale((String)zoneDisplayTestData[testNum][1]); 1779 TimeZone zone = TimeZone.getTimeZone((String)zoneDisplayTestData[testNum][0]); 1780 String displayName = zone.getDisplayName(((Boolean)zoneDisplayTestData[testNum][2]).booleanValue(), 1781 ((Integer)zoneDisplayTestData[testNum][3]).intValue()); 1782 if (!displayName.equals(zoneDisplayTestData[testNum][4])) { 1783 if (isDevelopmentBuild 1784 && (isICUTimeZone || !((Boolean)zoneDisplayTestData[testNum][2]).booleanValue())) { 1785 sawAnError = true; 1786 errln("Incorrect time zone display name. zone = " 1787 + zoneDisplayTestData[testNum][0] + ",\n" 1788 + " locale = " + locale 1789 + ", style = " + (zoneDisplayTestData[testNum][3] == TZSHORT ? "SHORT" : "LONG") 1790 + ", Summertime = " + zoneDisplayTestData[testNum][2] + "\n" 1791 + " Expected " + zoneDisplayTestData[testNum][4] 1792 + ", Got " + displayName); 1793 } else { 1794 logln("Incorrect time zone display name. zone = " 1795 + zoneDisplayTestData[testNum][0] + ",\n" 1796 + " locale = " + locale 1797 + ", style = " + (zoneDisplayTestData[testNum][3] == TZSHORT ? "SHORT" : "LONG") 1798 + ", Summertime = " + zoneDisplayTestData[testNum][2] + "\n" 1799 + " Expected " + zoneDisplayTestData[testNum][4] 1800 + ", Got " + displayName); 1801 } 1802 } 1803 } 1804 if (sawAnError) { 1805 logln("Note: Errors could be the result of changes to zoneStrings locale data"); 1806 } 1807 } 1808 1809 /* 1810 * Test case for hashCode problem reported by ticket#7690 OlsonTimeZone.hashCode() throws NPE. 1811 */ 1812 public void TestHashCode() { 1813 String[] ids = TimeZone.getAvailableIDs(); 1814 1815 for (String id: ids) { 1816 TimeZone tz1 = TimeZone.getTimeZone(id); 1817 TimeZone tz2 = TimeZone.getTimeZone(id); 1818 1819 // hash code are same for the same time zone 1820 if (tz1.hashCode() != tz2.hashCode()) { 1821 errln("Fail: Two time zone instances for " + id + " have different hash values."); 1822 } 1823 // string representation should be also same 1824 if (!tz1.toString().equals(tz2.toString())) { 1825 errln("Fail: Two time zone instances for " + id + " have different toString() values."); 1826 } 1827 } 1828 } 1829 1830 /* 1831 * Test case for getRegion 1832 */ 1833 public void TestGetRegion() { 1834 final String[][] TEST_DATA = { 1835 {"America/Los_Angeles", "US"}, 1836 {"America/Indianapolis", "US"}, // CLDR canonical, Olson backward 1837 {"America/Indiana/Indianapolis", "US"}, // CLDR alias 1838 {"Mexico/General", "MX"}, // Link America/Mexico_City, Olson backward 1839 {"Etc/UTC", "001"}, 1840 {"EST5EDT", "001"}, 1841 {"PST", "US"}, // Link America/Los_Angeles 1842 {"Europe/Helsinki", "FI"}, 1843 {"Europe/Mariehamn", "AX"}, // Link Europe/Helsinki, but in zone.tab 1844 {"Asia/Riyadh", "SA"}, 1845 // tz file solar87 was removed from tzdata2013i 1846 // {"Asia/Riyadh87", "001"}, // this should be "SA" actually, but not in zone.tab 1847 {"Etc/Unknown", null}, // CLDR canonical, but not a sysmte zone ID 1848 {"bogus", null}, // bogus 1849 {"GMT+08:00", null}, // a custom ID, not a system zone ID 1850 }; 1851 1852 for (String[] test : TEST_DATA) { 1853 try { 1854 String region = TimeZone.getRegion(test[0]); 1855 if (!region.equals(test[1])) { 1856 if (test[1] == null) { 1857 errln("Fail: getRegion(\"" + test[0] + "\") returns " 1858 + region + " [expected: IllegalArgumentException]"); 1859 } else { 1860 errln("Fail: getRegion(\"" + test[0] + "\") returns " 1861 + region + " [expected: " + test[1] + "]"); 1862 } 1863 } 1864 } catch (IllegalArgumentException e) { 1865 if (test[1] != null) { 1866 errln("Fail: getRegion(\"" + test[0] 1867 + "\") throws IllegalArgumentException [expected: " + test[1] + "]"); 1868 } 1869 } 1870 } 1871 } 1872 1873 public void TestZoneFields() { 1874 assertEquals("UNKNOWN_ZONE wrong ID", "Etc/Unknown", TimeZone.UNKNOWN_ZONE.getID()); 1875 assertEquals("UNKNOWN_ZONE wrong offset", 0, TimeZone.UNKNOWN_ZONE.getRawOffset()); 1876 assertFalse("UNKNOWN_ZONE uses DST", TimeZone.UNKNOWN_ZONE.useDaylightTime()); 1877 1878 assertEquals("GMT_ZONE wrong ID", "Etc/GMT", TimeZone.GMT_ZONE.getID()); 1879 assertEquals("GMT_ZONE wrong offset", 0, TimeZone.GMT_ZONE.getRawOffset()); 1880 assertFalse("GMT_ZONE uses DST", TimeZone.GMT_ZONE.useDaylightTime()); 1881 } 1882 1883 /* 1884 * Test case for Freezable 1885 */ 1886 public void TestFreezable() { 1887 // Test zones - initially thawed 1888 TimeZone[] ZA1 = { 1889 TimeZone.getDefault(), 1890 TimeZone.getTimeZone("America/Los_Angeles", TimeZone.TIMEZONE_ICU), 1891 TimeZone.getTimeZone("America/Los_Angeles", TimeZone.TIMEZONE_JDK), 1892 new SimpleTimeZone(0, "stz"), 1893 new RuleBasedTimeZone("rbtz", new InitialTimeZoneRule("rbtz0", 0, 0)), 1894 VTimeZone.create("America/New_York"), 1895 }; 1896 1897 checkThawed(ZA1, "ZA1"); 1898 // freeze 1899 for (int i = 0; i < ZA1.length; i++) { 1900 ZA1[i].freeze(); 1901 } 1902 checkFrozen(ZA1, "ZA1(frozen)"); 1903 1904 // Test zones - initially frozen 1905 final TimeZone[] ZA2 = { 1906 TimeZone.GMT_ZONE, 1907 TimeZone.UNKNOWN_ZONE, 1908 TimeZone.getFrozenTimeZone("America/Los_Angeles"), 1909 new SimpleTimeZone(3600000, "frz_stz").freeze(), 1910 new RuleBasedTimeZone("frz_rbtz", new InitialTimeZoneRule("frz_rbtz0", 3600000, 0)).freeze(), 1911 VTimeZone.create("Asia/Tokyo").freeze(), 1912 }; 1913 1914 checkFrozen(ZA2, "ZA2"); 1915 TimeZone[] ZA2_thawed = new TimeZone[ZA2.length]; 1916 // create thawed clone 1917 for (int i = 0; i < ZA2_thawed.length; i++) { 1918 ZA2_thawed[i] = ZA2[i].cloneAsThawed(); 1919 } 1920 checkThawed(ZA2_thawed, "ZA2(thawed)"); 1921 1922 } 1923 1924 private void checkThawed(TimeZone[] thawedZones, String zaName) { 1925 for (int i = 0; i < thawedZones.length; i++) { 1926 if (thawedZones[i].isFrozen()) { 1927 errln("Fail: " + zaName + "[" + i + "] is frozen."); 1928 } 1929 1930 // clone 1931 TimeZone copy = (TimeZone)thawedZones[i].clone(); 1932 if (thawedZones[i] == copy || !thawedZones[i].equals(copy)) { 1933 errln("Fail: " + zaName + "[" + i + "] - clone does not work."); 1934 } 1935 1936 // cloneAsThawed 1937 TimeZone thawed = (TimeZone)thawedZones[i].cloneAsThawed(); 1938 if (thawed.isFrozen() || !thawedZones[i].equals(thawed)) { 1939 errln("Fail: " + zaName + "[" + i + "] - cloneAsThawed does not work."); 1940 } 1941 1942 // setID 1943 try { 1944 String newID = "foo"; 1945 thawedZones[i].setID(newID); 1946 if (!thawedZones[i].getID().equals(newID)) { 1947 errln("Fail: " + zaName + "[" + i + "] - setID(\"" + newID + "\") does not work."); 1948 } 1949 } catch (UnsupportedOperationException e) { 1950 errln("Fail: " + zaName + "[" + i + "] - setID throws UnsupportedOperationException."); 1951 } 1952 1953 // setRawOffset 1954 if (!(thawedZones[i] instanceof RuleBasedTimeZone)) { // RuleBasedTimeZone does not supprot setRawOffset 1955 try { 1956 int newOffset = -3600000; 1957 thawedZones[i].setRawOffset(newOffset); 1958 if (thawedZones[i].getRawOffset() != newOffset) { 1959 errln("Fail: " + zaName + "[" + i + "] - setRawOffset(" + newOffset + ") does not work."); 1960 } 1961 } catch (UnsupportedOperationException e) { 1962 errln("Fail: " + zaName + "[" + i + "] - setRawOffset throws UnsupportedOperationException."); 1963 } 1964 } 1965 1966 if (thawedZones[i] instanceof SimpleTimeZone) { 1967 SimpleTimeZone stz = (SimpleTimeZone)thawedZones[i]; 1968 // setDSTSavings 1969 try { 1970 int newDSTSavings = 1800000; 1971 stz.setDSTSavings(newDSTSavings); 1972 if (stz.getDSTSavings() != newDSTSavings) { 1973 errln("Fail: (SimpleTimeZone)" + zaName + "[" + i + "] - setDSTSavings(" + newDSTSavings + ") does not work."); 1974 } 1975 } catch (UnsupportedOperationException e) { 1976 errln("Fail: (SimpleTimeZone)" + zaName + "[" + i + "] - setDSTSavings throws UnsupportedOperationException."); 1977 } 1978 // setStartRule 1979 try { 1980 stz.setStartRule(Calendar.JANUARY, -1, Calendar.SUNDAY, 0); 1981 } catch (UnsupportedOperationException e) { 1982 errln("Fail: (SimpleTimeZone)" + zaName + "[" + i + "] - setStartRule throws UnsupportedOperationException."); 1983 } 1984 // setEndRule 1985 try { 1986 stz.setEndRule(Calendar.DECEMBER, 1, Calendar.SUNDAY, 0); 1987 } catch (UnsupportedOperationException e) { 1988 errln("Fail: (SimpleTimeZone)" + zaName + "[" + i + "] - setEndRule throws UnsupportedOperationException."); 1989 } 1990 // setStartYear 1991 try { 1992 stz.setStartYear(2000); 1993 } catch (UnsupportedOperationException e) { 1994 errln("Fail: (SimpleTimeZone)" + zaName + "[" + i + "] - setStartYear throws UnsupportedOperationException."); 1995 } 1996 } else if (thawedZones[i] instanceof RuleBasedTimeZone) { 1997 RuleBasedTimeZone rbtz = (RuleBasedTimeZone)thawedZones[i]; 1998 // addTransitionRule 1999 try { 2000 TimeArrayTimeZoneRule tr1 = new TimeArrayTimeZoneRule("tr1", 7200000, 0, new long[] {0}, DateTimeRule.UTC_TIME); 2001 rbtz.addTransitionRule(tr1); 2002 } catch (UnsupportedOperationException e) { 2003 errln("Fail: (RuleBasedTimeZone)" + zaName + "[" + i + "] - addTransitionRule throws UnsupportedOperationException."); 2004 } 2005 } else if (thawedZones[i] instanceof VTimeZone) { 2006 VTimeZone vtz = (VTimeZone)thawedZones[i]; 2007 // setTZURL 2008 try { 2009 String tzUrl = "http://icu-project.org/timezone"; 2010 vtz.setTZURL(tzUrl); 2011 if (!vtz.getTZURL().equals(tzUrl)) { 2012 errln("Fail: (VTimeZone)" + zaName + "[" + i + "] - setTZURL does not work."); 2013 } 2014 } catch (UnsupportedOperationException e) { 2015 errln("Fail: (VTimeZone)" + zaName + "[" + i + "] - setTZURL throws UnsupportedOperationException."); 2016 } 2017 // setLastModified 2018 try { 2019 Date d = new Date(); 2020 vtz.setLastModified(d); 2021 if (!vtz.getLastModified().equals(d)) { 2022 errln("Fail: (VTimeZone)" + zaName + "[" + i + "] - setLastModified does not work."); 2023 } 2024 } catch (UnsupportedOperationException e) { 2025 errln("Fail: (VTimeZone)" + zaName + "[" + i + "] - setLastModified throws UnsupportedOperationException."); 2026 } 2027 } 2028 } 2029 } 2030 2031 private void checkFrozen(TimeZone[] frozenZones, String zaName) { 2032 for (int i = 0; i < frozenZones.length; i++) { 2033 if (!frozenZones[i].isFrozen()) { 2034 errln("Fail: " + zaName + "[" + i + "] is not frozen."); 2035 } 2036 2037 // clone 2038 TimeZone copy = (TimeZone)frozenZones[i].clone(); 2039 if (frozenZones[i] != copy) { 2040 errln("Fail: " + zaName + "[" + i + "] - clone does not return the object itself."); 2041 } 2042 2043 // cloneAsThawed 2044 TimeZone thawed = (TimeZone)frozenZones[i].cloneAsThawed(); 2045 if (thawed.isFrozen() || !frozenZones[i].equals(thawed)) { 2046 errln("Fail: " + zaName + "[" + i + "] - cloneAsThawed does not work."); 2047 } 2048 2049 // setID 2050 try { 2051 String newID = "foo"; 2052 frozenZones[i].setID(newID); 2053 errln("Fail: " + zaName + "[" + i + "] - setID must throw UnsupportedOperationException."); 2054 } catch (UnsupportedOperationException e) { 2055 // OK 2056 } 2057 2058 // setRawOffset 2059 if (!(frozenZones[i] instanceof RuleBasedTimeZone)) { // RuleBasedTimeZone does not supprot setRawOffset 2060 try { 2061 int newOffset = -3600000; 2062 frozenZones[i].setRawOffset(newOffset); 2063 errln("Fail: " + zaName + "[" + i + "] - setRawOffset must throw UnsupportedOperationException."); 2064 } catch (UnsupportedOperationException e) { 2065 // OK 2066 } 2067 } 2068 2069 if (frozenZones[i] instanceof SimpleTimeZone) { 2070 SimpleTimeZone stz = (SimpleTimeZone)frozenZones[i]; 2071 // setDSTSavings 2072 try { 2073 int newDSTSavings = 1800000; 2074 stz.setDSTSavings(newDSTSavings); 2075 errln("Fail: (SimpleTimeZone)" + zaName + "[" + i + "] - setDSTSavings must throw UnsupportedOperationException."); 2076 } catch (UnsupportedOperationException e) { 2077 // OK 2078 } 2079 // setStartRule 2080 try { 2081 stz.setStartRule(Calendar.JANUARY, -1, Calendar.SUNDAY, 0); 2082 errln("Fail: (SimpleTimeZone)" + zaName + "[" + i + "] - setStartRule must throw UnsupportedOperationException."); 2083 } catch (UnsupportedOperationException e) { 2084 // OK 2085 } 2086 // setEndRule 2087 try { 2088 stz.setEndRule(Calendar.DECEMBER, 1, Calendar.SUNDAY, 0); 2089 errln("Fail: (SimpleTimeZone)" + zaName + "[" + i + "] - setEndRule must throw UnsupportedOperationException."); 2090 } catch (UnsupportedOperationException e) { 2091 // OK 2092 } 2093 // setStartYear 2094 try { 2095 stz.setStartYear(2000); 2096 errln("Fail: (SimpleTimeZone)" + zaName + "[" + i + "] - setStartYear must throw UnsupportedOperationException."); 2097 } catch (UnsupportedOperationException e) { 2098 // OK 2099 } 2100 } else if (frozenZones[i] instanceof RuleBasedTimeZone) { 2101 RuleBasedTimeZone rbtz = (RuleBasedTimeZone)frozenZones[i]; 2102 // addTransitionRule 2103 try { 2104 TimeArrayTimeZoneRule tr1 = new TimeArrayTimeZoneRule("tr1", 7200000, 0, new long[] {0}, DateTimeRule.UTC_TIME); 2105 rbtz.addTransitionRule(tr1); 2106 errln("Fail: (RuleBasedTimeZone)" + zaName + "[" + i + "] - addTransitionRule must throw UnsupportedOperationException."); 2107 } catch (UnsupportedOperationException e) { 2108 // OK 2109 } 2110 } else if (frozenZones[i] instanceof VTimeZone) { 2111 VTimeZone vtz = (VTimeZone)frozenZones[i]; 2112 // setTZURL 2113 try { 2114 String tzUrl = "http://icu-project.org/timezone"; 2115 vtz.setTZURL(tzUrl); 2116 errln("Fail: (VTimeZone)" + zaName + "[" + i + "] - setTZURL must throw UnsupportedOperationException."); 2117 } catch (UnsupportedOperationException e) { 2118 // OK 2119 } 2120 // setLastModified 2121 try { 2122 Date d = new Date(); 2123 vtz.setLastModified(d); 2124 errln("Fail: (VTimeZone)" + zaName + "[" + i + "] - setLastModified must throw UnsupportedOperationException."); 2125 } catch (UnsupportedOperationException e) { 2126 // OK 2127 } 2128 } 2129 } 2130 } 2131 2132 public void TestObservesDaylightTime() { 2133 boolean observesDaylight; 2134 long current = System.currentTimeMillis(); 2135 2136 String[] tzids = TimeZone.getAvailableIDs(); 2137 for (String tzid : tzids) { 2138 // OlsonTimeZone 2139 TimeZone tz = TimeZone.getTimeZone(tzid, TimeZone.TIMEZONE_ICU); 2140 observesDaylight = tz.observesDaylightTime(); 2141 if (observesDaylight != isDaylightTimeAvailable(tz, current)) { 2142 errln("Fail: [OlsonTimeZone] observesDaylightTime() returned " + observesDaylight + " for " + tzid); 2143 } 2144 2145 // RuleBasedTimeZone 2146 RuleBasedTimeZone rbtz = createRBTZ((BasicTimeZone)tz, current); 2147 boolean observesDaylightRBTZ = rbtz.observesDaylightTime(); 2148 if (observesDaylightRBTZ != isDaylightTimeAvailable(rbtz, current)) { 2149 errln("Fail: [RuleBasedTimeZone] observesDaylightTime() returned " + observesDaylightRBTZ + " for " + rbtz.getID()); 2150 } else if (observesDaylight != observesDaylightRBTZ) { 2151 errln("Fail: RuleBasedTimeZone " + rbtz.getID() + " returns " + observesDaylightRBTZ + ", but different from match OlsonTimeZone"); 2152 } 2153 2154 // JavaTimeZone 2155 tz = TimeZone.getTimeZone(tzid, TimeZone.TIMEZONE_JDK); 2156 observesDaylight = tz.observesDaylightTime(); 2157 if (observesDaylight != isDaylightTimeAvailable(tz, current)) { 2158 errln("Fail: [JavaTimeZone] observesDaylightTime() returned " + observesDaylight + " for " + tzid); 2159 } 2160 2161 // VTimeZone 2162 tz = VTimeZone.getTimeZone(tzid); 2163 observesDaylight = tz.observesDaylightTime(); 2164 if (observesDaylight != isDaylightTimeAvailable(tz, current)) { 2165 errln("Fail: [VTimeZone] observesDaylightTime() returned " + observesDaylight + " for " + tzid); 2166 } 2167 } 2168 2169 // SimpleTimeZone 2170 SimpleTimeZone[] stzs = { 2171 new SimpleTimeZone(0, "STZ0"), 2172 new SimpleTimeZone(-5*60*60*1000, "STZ-5D", Calendar.MARCH, 2, Calendar.SUNDAY, 2*60*60*1000, 2173 Calendar.NOVEMBER, 1, Calendar.SUNDAY, 2*60*60*1000), 2174 }; 2175 for (SimpleTimeZone stz : stzs) { 2176 observesDaylight = stz.observesDaylightTime(); 2177 if (observesDaylight != isDaylightTimeAvailable(stz, current)) { 2178 errln("Fail: [SimpleTimeZone] observesDaylightTime() returned " + observesDaylight + " for " + stz.getID()); 2179 } 2180 } 2181 } 2182 2183 private static boolean isDaylightTimeAvailable(TimeZone tz, long start) { 2184 if (tz.inDaylightTime(new Date(start))) { 2185 return true; 2186 } 2187 2188 long date; 2189 if (tz instanceof BasicTimeZone) { 2190 BasicTimeZone btz = (BasicTimeZone)tz; 2191 // check future transitions, up to 100 2192 date = start; 2193 for (int i = 0; i < 100; i++) { 2194 TimeZoneTransition tzt = btz.getNextTransition(date, false); 2195 if (tzt == null) { 2196 // no more transitions 2197 break; 2198 } 2199 if (tzt.getTo().getDSTSavings() != 0) { 2200 return true; 2201 } 2202 date = tzt.getTime(); 2203 } 2204 } else { 2205 // check future times by incrementing 30 days, up to 200 times (about 16 years) 2206 final long inc = 30L * 24 * 60 * 60 * 1000; 2207 int[] offsets = new int[2]; 2208 date = start + inc; 2209 for (int i = 0; i < 200; i++, date += inc) { 2210 tz.getOffset(date, false, offsets); 2211 if (offsets[1] != 0) { 2212 return true; 2213 } 2214 } 2215 } 2216 return false; 2217 } 2218 2219 private static RuleBasedTimeZone createRBTZ(BasicTimeZone btz, long start) { 2220 TimeZoneRule[] rules = btz.getTimeZoneRules(start); 2221 RuleBasedTimeZone rbtz = new RuleBasedTimeZone("RBTZ:btz.getID()", (InitialTimeZoneRule)rules[0]); 2222 for (int i = 1; i < rules.length; i++) { 2223 rbtz.addTransitionRule(rules[i]); 2224 } 2225 return rbtz; 2226 } 2227 2228 public void TestGetWindowsID() { 2229 String[][] TESTDATA = { 2230 {"America/New_York", "Eastern Standard Time"}, 2231 {"America/Montreal", "Eastern Standard Time"}, 2232 {"America/Los_Angeles", "Pacific Standard Time"}, 2233 {"America/Vancouver", "Pacific Standard Time"}, 2234 {"Asia/Shanghai", "China Standard Time"}, 2235 {"Asia/Chongqing", "China Standard Time"}, 2236 {"America/Indianapolis", "US Eastern Standard Time"}, // CLDR canonical name 2237 {"America/Indiana/Indianapolis", "US Eastern Standard Time"}, // tzdb canonical name 2238 {"Asia/Khandyga", "Yakutsk Standard Time"}, 2239 {"Australia/Eucla", null}, // No Windows ID mapping 2240 {"Bogus", null}, 2241 }; 2242 2243 for (String[] data : TESTDATA) { 2244 String winID = TimeZone.getWindowsID(data[0]); 2245 assertEquals("Fail: ID=" + data[0], data[1], winID); 2246 } 2247 } 2248 2249 public void TestGetIDForWindowsID() { 2250 final String[][] TESTDATA = { 2251 {"Eastern Standard Time", null, "America/New_York"}, 2252 {"Eastern Standard Time", "US", "America/New_York"}, 2253 {"Eastern Standard Time", "CA", "America/Toronto"}, 2254 {"Eastern Standard Time", "CN", "America/New_York"}, 2255 {"China Standard Time", null, "Asia/Shanghai"}, 2256 {"China Standard Time", "CN", "Asia/Shanghai"}, 2257 {"China Standard Time", "HK", "Asia/Hong_Kong"}, 2258 {"Mid-Atlantic Standard Time", null, null}, // No tz database mapping 2259 {"Bogus", null, null}, 2260 }; 2261 2262 for (String[] data : TESTDATA) { 2263 String id = TimeZone.getIDForWindowsID(data[0], data[1]); 2264 assertEquals("Fail: Windows ID=" + data[0] + ", Region=" + data[1], 2265 data[2], id); 2266 } 2267 } 2268 } 2269 2270 //eof 2271