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