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