/* GENERATED SOURCE. DO NOT MODIFY. */ // © 2016 and later: Unicode, Inc. and others. // License & terms of use: http://www.unicode.org/copyright.html /** ******************************************************************************* * Copyright (C) 2000-2016, International Business Machines Corporation and * others. All Rights Reserved. ******************************************************************************* */ package android.icu.dev.test.timezone; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.util.Arrays; import java.util.Date; import java.util.List; import java.util.Locale; import java.util.Set; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; import android.icu.dev.test.CoreTestFmwk; import android.icu.dev.test.TestFmwk; import android.icu.impl.ICUData; import android.icu.impl.TimeZoneAdapter; import android.icu.text.SimpleDateFormat; import android.icu.util.BasicTimeZone; import android.icu.util.Calendar; import android.icu.util.DateTimeRule; import android.icu.util.GregorianCalendar; import android.icu.util.InitialTimeZoneRule; import android.icu.util.RuleBasedTimeZone; import android.icu.util.SimpleTimeZone; import android.icu.util.TimeArrayTimeZoneRule; import android.icu.util.TimeZone; import android.icu.util.TimeZone.SystemTimeZoneType; import android.icu.util.TimeZoneRule; import android.icu.util.TimeZoneTransition; import android.icu.util.ULocale; import android.icu.util.UResourceBundle; import android.icu.util.VTimeZone; import android.icu.util.VersionInfo; import android.icu.testsharding.MainTestShard; /** * @test 1.22 99/09/21 * @bug 4028006 4044013 4096694 4107276 4107570 4112869 4130885 * @summary test TimeZone * @build TimeZoneTest */ @MainTestShard @RunWith(JUnit4.class) public class TimeZoneTest extends CoreTestFmwk { static final int millisPerHour = 3600000; // Some test case data is current date/tzdata version sensitive and producing errors // when year/rule are changed. Although we want to keep our eyes on test failures // caused by tzdata changes while development, keep maintaining test data in maintenance // stream is a little bit hassle. ICU 49 or later versions are using minor version field // to indicate a development build (0) or official release build (others). For development // builds, a test failure triggers an error, while release builds only report them in // verbose mode with logln. static final boolean isDevelopmentBuild = (VersionInfo.ICU_VERSION.getMinor() == 0); /** * NOTE: As of ICU 2.8, the mapping of 3-letter legacy aliases * to `real' Olson IDs is under control of the underlying JDK. * This test may fail on one JDK and pass on another; don't be * too concerned. Alan * * Bug 4130885 * Certain short zone IDs, used since 1.1.x, are incorrect. * * The worst of these is: * * "CAT" (Central African Time) should be GMT+2:00, but instead returns a * zone at GMT-1:00. The zone at GMT-1:00 should be called EGT, CVT, EGST, * or AZOST, depending on which zone is meant, but in no case is it CAT. * * Other wrong zone IDs: * * ECT (European Central Time) GMT+1:00: ECT is Ecuador Time, * GMT-5:00. European Central time is abbreviated CEST. * * SST (Solomon Island Time) GMT+11:00. SST is actually Samoa Standard Time, * GMT-11:00. Solomon Island time is SBT. * * NST (New Zealand Time) GMT+12:00. NST is the abbreviation for * Newfoundland Standard Time, GMT-3:30. New Zealanders use NZST. * * AST (Alaska Standard Time) GMT-9:00. [This has already been noted in * another bug.] It should be "AKST". AST is Atlantic Standard Time, * GMT-4:00. * * PNT (Phoenix Time) GMT-7:00. PNT usually means Pitcairn Time, * GMT-8:30. There is no standard abbreviation for Phoenix time, as distinct * from MST with daylight savings. * * In addition to these problems, a number of zones are FAKE. That is, they * don't match what people use in the real world. * * FAKE zones: * * EET (should be EEST) * ART (should be EEST) * MET (should be IRST) * NET (should be AMST) * PLT (should be PKT) * BST (should be BDT) * VST (should be ICT) * CTT (should be CST) + * ACT (should be CST) + * AET (should be EST) + * MIT (should be WST) + * IET (should be EST) + * PRT (should be AST) + * CNT (should be NST) * AGT (should be ARST) * BET (should be EST) + * * + A zone with the correct name already exists and means something * else. E.g., EST usually indicates the US Eastern zone, so it cannot be * used for Brazil (BET). */ @Test public void TestShortZoneIDs() throws Exception { // Note: If the default TimeZone type is JDK, some time zones // may differ from the test data below. For example, "MST" on // IBM JRE is an alias of "America/Denver" for supporting Java 1.1 // backward compatibility, while Olson tzdata (and ICU) treat it // as -7hour fixed offset/no DST. boolean isJDKTimeZone = (TimeZone.getDefaultTimeZoneType() == TimeZone.TIMEZONE_JDK); if (isJDKTimeZone) { logln("Warning: Using JDK TimeZone. Some test cases may not return expected results."); } ZoneDescriptor[] REFERENCE_LIST = { new ZoneDescriptor("HST", -600, false), // Olson northamerica -10:00 new ZoneDescriptor("AST", -540, true), // ICU Link - America/Anchorage new ZoneDescriptor("PST", -480, true), // ICU Link - America/Los_Angeles new ZoneDescriptor("PNT", -420, false), // ICU Link - America/Phoenix new ZoneDescriptor("MST", -420, false), // updated Aug 2003 aliu new ZoneDescriptor("CST", -360, true), // Olson northamerica -7:00 new ZoneDescriptor("IET", -300, true), // ICU Link - America/Indiana/Indianapolis new ZoneDescriptor("EST", -300, false), // Olson northamerica -5:00 new ZoneDescriptor("PRT", -240, false), // ICU Link - America/Puerto_Rico new ZoneDescriptor("CNT", -210, true), // ICU Link - America/St_Johns new ZoneDescriptor("AGT", -180, false), // ICU Link - America/Argentina/Buenos_Aires // Per https://mm.icann.org/pipermail/tz-announce/2019-July/000056.html // Brazil has canceled DST and will stay on standard time indefinitely. new ZoneDescriptor("BET", -180, false), // ICU Link - America/Sao_Paulo new ZoneDescriptor("GMT", 0, false), // Olson etcetera Link - Etc/GMT new ZoneDescriptor("UTC", 0, false), // Olson etcetera 0 new ZoneDescriptor("ECT", 60, true), // ICU Link - Europe/Paris new ZoneDescriptor("MET", 60, true), // Olson europe 1:00 C-Eur new ZoneDescriptor("CAT", 120, false), // ICU Link - Africa/Harare new ZoneDescriptor("ART", 120, false), // ICU Link - Africa/Cairo new ZoneDescriptor("EET", 120, true), // Olson europe 2:00 EU new ZoneDescriptor("EAT", 180, false), // ICU Link - Africa/Addis_Ababa new ZoneDescriptor("NET", 240, false), // ICU Link - Asia/Yerevan new ZoneDescriptor("PLT", 300, false), // ICU Link - Asia/Karachi new ZoneDescriptor("IST", 330, false), // ICU Link - Asia/Kolkata new ZoneDescriptor("BST", 360, false), // ICU Link - Asia/Dhaka new ZoneDescriptor("VST", 420, false), // ICU Link - Asia/Ho_Chi_Minh new ZoneDescriptor("CTT", 480, false), // ICU Link - Asia/Shanghai new ZoneDescriptor("JST", 540, false), // ICU Link - Asia/Tokyo new ZoneDescriptor("ACT", 570, false), // ICU Link - Australia/Darwin new ZoneDescriptor("AET", 600, true), // ICU Link - Australia/Sydney new ZoneDescriptor("SST", 660, false), // ICU Link - Pacific/Guadalcanal new ZoneDescriptor("NST", 720, true), // ICU Link - Pacific/Auckland new ZoneDescriptor("MIT", 780, false), // ICU Link - Pacific/Apia new ZoneDescriptor("Etc/Unknown", 0, false), // CLDR new ZoneDescriptor("SystemV/AST4ADT", -240, true), new ZoneDescriptor("SystemV/EST5EDT", -300, true), new ZoneDescriptor("SystemV/CST6CDT", -360, true), new ZoneDescriptor("SystemV/MST7MDT", -420, true), new ZoneDescriptor("SystemV/PST8PDT", -480, true), new ZoneDescriptor("SystemV/YST9YDT", -540, true), new ZoneDescriptor("SystemV/AST4", -240, false), new ZoneDescriptor("SystemV/EST5", -300, false), new ZoneDescriptor("SystemV/CST6", -360, false), new ZoneDescriptor("SystemV/MST7", -420, false), new ZoneDescriptor("SystemV/PST8", -480, false), new ZoneDescriptor("SystemV/YST9", -540, false), new ZoneDescriptor("SystemV/HST10", -600, false), }; for (int i=0; i i2.offset) return 1; if (i1.offset < i2.offset) return -1; if (i1.daylight && !i2.daylight) return 1; if (!i1.daylight && i2.daylight) return -1; return i1.id.compareTo(i2.id); } } /** * As part of the VM fix (see CCC approved RFE 4028006, bug * 4044013), TimeZone.getTimeZone() has been modified to recognize * generic IDs of the form GMT[+-]hh:mm, GMT[+-]hhmm, and * GMT[+-]hh. Test this behavior here. * * Bug 4044013 */ @Test public void TestCustomParse() { String[] DATA = { // ID offset(sec) output ID "GMT", "0", "GMT", // system ID "GMT-YOUR.AD.HERE", "0", TimeZone.UNKNOWN_ZONE_ID, "GMT0", "0", "GMT0", // system ID "GMT+0", "0", "GMT+0", // system ID "GMT+1", "3600", "GMT+01:00", "GMT-0030", "-1800", "GMT-00:30", "GMT+15:99", "0", TimeZone.UNKNOWN_ZONE_ID, "GMT+", "0", TimeZone.UNKNOWN_ZONE_ID, "GMT-", "0", TimeZone.UNKNOWN_ZONE_ID, "GMT+0:", "0", TimeZone.UNKNOWN_ZONE_ID, "GMT-:", "0", TimeZone.UNKNOWN_ZONE_ID, "GMT+0010", "600", "GMT+00:10", "GMT-10", "-36000", "GMT-10:00", "GMT+30", "0", TimeZone.UNKNOWN_ZONE_ID, "GMT-3:30", "-12600", "GMT-03:30", "GMT-230", "-9000", "GMT-02:30", "GMT+05:13:05", "18785", "GMT+05:13:05", "GMT-71023", "-25823", "GMT-07:10:23", "GMT+01:23:45:67", "0", TimeZone.UNKNOWN_ZONE_ID, "GMT+01:234", "0", TimeZone.UNKNOWN_ZONE_ID, "GMT-2:31:123", "0", TimeZone.UNKNOWN_ZONE_ID, "GMT+3:75", "0", TimeZone.UNKNOWN_ZONE_ID, "GMT-01010101", "0", TimeZone.UNKNOWN_ZONE_ID, "GMT-4E58", "0", TimeZone.UNKNOWN_ZONE_ID, // ICU-22637 "GMT-4e58", "0", TimeZone.UNKNOWN_ZONE_ID, // ICU-22637 "GMT-1E01", "0", TimeZone.UNKNOWN_ZONE_ID, // ICU-22637 "GMT-2E01", "0", TimeZone.UNKNOWN_ZONE_ID, // ICU-22637 "GMT-2e01", "0", TimeZone.UNKNOWN_ZONE_ID, // ICU-22637 "GMT-9e02", "0", TimeZone.UNKNOWN_ZONE_ID, // ICU-22637 "GMT-1e03", "0", TimeZone.UNKNOWN_ZONE_ID, // ICU-22637 "GMT-2e03", "0", TimeZone.UNKNOWN_ZONE_ID, // ICU-22637 "GMT-500M", "0", TimeZone.UNKNOWN_ZONE_ID, // ICU-22637 "GMT-500T", "0", TimeZone.UNKNOWN_ZONE_ID, // ICU-22637 "GMT-9E00", "0", TimeZone.UNKNOWN_ZONE_ID, // ICU-22637 "GMT-0X0F", "0", TimeZone.UNKNOWN_ZONE_ID, // ICU-22637 "GMT-0x0F", "0", TimeZone.UNKNOWN_ZONE_ID, // ICU-22637 "GMT-0x12", "0", TimeZone.UNKNOWN_ZONE_ID, // ICU-22637 "GMT-B111", "0", TimeZone.UNKNOWN_ZONE_ID, // ICU-22637 "GMT-b111", "0", TimeZone.UNKNOWN_ZONE_ID, // ICU-22637 "GMT-0b11", "0", TimeZone.UNKNOWN_ZONE_ID, // ICU-22637 "GMT-๑๒", "-43200", "GMT-12:00", // ICU-22637 "GMT-๑๒:๓๔", "-45240", "GMT-12:34", // ICU-22637 "GMT+๑๒:๓๔:๕๖", "45296", "GMT+12:34:56", // ICU-22637 }; for (int i = 0; i < DATA.length; i += 3) { String id = DATA[i]; int offset = Integer.parseInt(DATA[i+1]); String expId = DATA[i+2]; TimeZone zone = TimeZone.getTimeZone(id); String gotID = zone.getID(); int gotOffset = zone.getRawOffset()/1000; logln(id + " -> " + gotID + " " + gotOffset); if (offset != gotOffset) { errln("FAIL: Unexpected offset for " + id + " - returned:" + gotOffset + " expected:" + offset); } if (!expId.equals(gotID)) { if (TimeZone.getDefaultTimeZoneType() != TimeZone.TIMEZONE_ICU) { logln("ID for " + id + " - returned:" + gotID + " expected:" + expId); } else { errln("FAIL: Unexpected ID for " + id + " - returned:" + gotID + " expected:" + expId); } } } } /** * Test the basic functionality of the getDisplayName() API. * * Bug 4112869 * Bug 4028006 * * See also API change request A41. * * 4/21/98 - make smarter, so the test works if the ext resources * are present or not. */ @Test public void TestDisplayName() { TimeZone zone = TimeZone.getTimeZone("PST"); String name = zone.getDisplayName(Locale.ENGLISH); logln("PST->" + name); // dlf - we now (3.4.1) return generic time if (!name.equals("Pacific Time")) errln("Fail: Expected \"Pacific Time\", got " + name + " for " + zone); //***************************************************************** // THE FOLLOWING LINES MUST BE UPDATED IF THE LOCALE DATA CHANGES // THE FOLLOWING LINES MUST BE UPDATED IF THE LOCALE DATA CHANGES // THE FOLLOWING LINES MUST BE UPDATED IF THE LOCALE DATA CHANGES //***************************************************************** // Test to allow the user to choose to get all the forms // (z, zzzz, Z, ZZZZ, v, vvvv) // todo: check to see whether we can test for all of pst, pdt, pt Object[] DATA = { // z and zzzz Boolean.FALSE, TimeZone.SHORT, "PST", Boolean.TRUE, TimeZone.SHORT, "PDT", Boolean.FALSE, TimeZone.LONG, "Pacific Standard Time", Boolean.TRUE, TimeZone.LONG, "Pacific Daylight Time", // v and vvvv Boolean.FALSE, TimeZone.SHORT_GENERIC, "PT", Boolean.TRUE, TimeZone.SHORT_GENERIC, "PT", Boolean.FALSE, TimeZone.LONG_GENERIC, "Pacific Time", Boolean.TRUE, TimeZone.LONG_GENERIC, "Pacific Time", // z and ZZZZ Boolean.FALSE, TimeZone.SHORT_GMT, "-0800", Boolean.TRUE, TimeZone.SHORT_GMT, "-0700", Boolean.FALSE, TimeZone.LONG_GMT, "GMT-08:00", Boolean.TRUE, TimeZone.LONG_GMT, "GMT-07:00", // V and VVVV Boolean.FALSE, TimeZone.SHORT_COMMONLY_USED, "PST", Boolean.TRUE, TimeZone.SHORT_COMMONLY_USED, "PDT", Boolean.FALSE, TimeZone.GENERIC_LOCATION, "Los Angeles Time", Boolean.TRUE, TimeZone.GENERIC_LOCATION, "Los Angeles Time", }; for (int i=0; i" + zone2.inDaylightTime(new Date())); name = zone2.getDisplayName(Locale.ENGLISH); logln("Modified PST->" + name); if (!name.equals("Pacific Time")) errln("Fail: Expected \"Pacific Time\""); // Make sure we get the default display format for Locales // with no display name data. Locale mt_MT = new Locale("mt", "MT"); name = zone.getDisplayName(mt_MT); //***************************************************************** // THE FOLLOWING LINE MUST BE UPDATED IF THE LOCALE DATA CHANGES // THE FOLLOWING LINE MUST BE UPDATED IF THE LOCALE DATA CHANGES // THE FOLLOWING LINE MUST BE UPDATED IF THE LOCALE DATA CHANGES //***************************************************************** logln("PST(mt_MT)->" + name); // Now be smart -- check to see if zh resource is even present. // If not, we expect the en fallback behavior. // in icu4j 2.1 we know we have the zh_CN locale data, though it's incomplete // /"DateFormatZoneData", UResourceBundle enRB = UResourceBundle.getBundleInstance(ICUData.ICU_BASE_NAME,Locale.ENGLISH); UResourceBundle mtRB = UResourceBundle.getBundleInstance(ICUData.ICU_BASE_NAME, mt_MT); boolean noZH = enRB == mtRB; if (noZH) { logln("Warning: Not testing the mt_MT behavior because resource is absent"); if (!name.equals("Pacific Standard Time")) errln("Fail: Expected Pacific Standard Time for PST in mt_MT but got "); } // dlf - we will use generic time, or if unavailable, GMT for standard time in the zone // - we now (3.4.1) have localizations for this zone, so change test string else if(!name.equals("\u0126in ta\u2019 Los Angeles") && !name.equals("GMT-08:00") && !name.equals("GMT-8:00") && !name.equals("GMT-0800") && !name.equals("GMT-800")) { errln("Fail: got '" + name + "', expected GMT-08:00 or something similar\n" + "************************************************************\n" + "THE ABOVE FAILURE MAY JUST MEAN THE LOCALE DATA HAS CHANGED\n" + "************************************************************"); } // Now try a non-existent zone zone2 = new SimpleTimeZone(90*60*1000, "xyzzy"); name = zone2.getDisplayName(Locale.ENGLISH); logln("GMT+90min->" + name); if (!name.equals("GMT+01:30") && !name.equals("GMT+1:30") && !name.equals("GMT+0130") && !name.equals("GMT+130")) errln("Fail: Expected GMT+01:30 or something similar"); // cover getDisplayName() - null arg ULocale save = ULocale.getDefault(); ULocale.setDefault(ULocale.US); name = zone2.getDisplayName(); logln("GMT+90min->" + name + "for default display locale"); if (!name.equals("GMT+01:30") && !name.equals("GMT+1:30") && !name.equals("GMT+0130") && !name.equals("GMT+130")) errln("Fail: Expected GMT+01:30 or something similar"); ULocale.setDefault(save); } @Test public void TestDisplayName2() { Date now = new Date(); String[] timezones = {"America/Chicago", "Europe/Moscow", "Europe/Rome", "Asia/Shanghai", "WET" }; String[] locales = {"en", "fr", "de", "ja", "zh_TW", "zh_Hans" }; for (int j = 0; j < locales.length; ++j) { ULocale locale = new ULocale(locales[j]); for (int i = 0; i < timezones.length; ++i) { TimeZone tz = TimeZone.getTimeZone(timezones[i]); String displayName0 = tz.getDisplayName(locale); SimpleDateFormat dt = new SimpleDateFormat("vvvv", locale); dt.setTimeZone(tz); String displayName1 = dt.format(now); // date value _does_ matter if we fallback to GMT logln(locale.getDisplayName() + ", " + tz.getID() + ": " + displayName0); if (!displayName1.equals(displayName0)) { // This could happen when the date used is in DST, // because TimeZone.getDisplayName(ULocale) may use // localized GMT format for the time zone's standard // time. if (tz.inDaylightTime(now)) { // Try getDisplayName with daylight argument displayName0 = tz.getDisplayName(true, TimeZone.LONG_GENERIC, locale); } if (!displayName1.equals(displayName0)) { errln(locale.getDisplayName() + ", " + tz.getID() + ": expected " + displayName1 + " but got: " + displayName0); } } } } } @Test public void TestGenericAPI() { // It's necessary to use a real existing time zone here, some systems (Android) will not // accept any arbitrary TimeZone object to be used as the default. String id = "GMT-12:00"; int offset = -12 * 60 * 60 * 1000; SimpleTimeZone zone = new SimpleTimeZone(offset, id); if (zone.useDaylightTime()) errln("FAIL: useDaylightTime should return false"); TimeZone zoneclone = (TimeZone)zone.clone(); if (!zoneclone.equals(zone)) errln("FAIL: clone or operator== failed"); zoneclone.setID("abc"); if (zoneclone.equals(zone)) errln("FAIL: clone or operator!= failed"); zoneclone = (TimeZone)zone.clone(); if (!zoneclone.equals(zone)) errln("FAIL: clone or operator== failed"); zoneclone.setRawOffset(45678); if (zoneclone.equals(zone)) errln("FAIL: clone or operator!= failed"); // set/getDefault TimeZone saveDefault = TimeZone.getDefault(); TimeZone.setDefault(zone); TimeZone defaultzone = TimeZone.getDefault(); if (defaultzone == zone) { errln("FAIL: Default object is identical, not clone"); } if (!defaultzone.equals(zone)) { errln("FAIL: Default object is not equal"); } java.util.TimeZone javaDefault = java.util.TimeZone.getDefault(); if (offset != javaDefault.getRawOffset() || !id.equals(javaDefault.getID())) { errln("FAIL: Java runtime default time zone is not synchronized"); } String anotheId = "AnotherZone"; int anotherOffset = 23456; SimpleTimeZone anotherZone = new SimpleTimeZone(anotherOffset, anotheId); TimeZone.setICUDefault(anotherZone); TimeZone newICUDefaultZone = TimeZone.getDefault(); if (newICUDefaultZone == anotherZone) { errln("FAIL: New ICU default object is identical, not clone"); } if (!newICUDefaultZone.equals(anotherZone)) { errln("FAIL: New ICU default object is not equal"); } javaDefault = java.util.TimeZone.getDefault(); if (offset != javaDefault.getRawOffset() || !id.equals(javaDefault.getID())) { errln("FAIL: Java runtime default time zone was updated"); } TimeZone.setDefault(saveDefault); String tzver = TimeZone.getTZDataVersion(); if (tzver != null && (tzver.length() == 5 || tzver.length() == 6) /* 4 digits + 1 or 2 letters */ ) { logln("PASS: tzdata version: " + tzver); } else { errln("FAIL: getTZDataVersion returned " + tzver); } } @Test public void TestRuleAPI() { // ErrorCode status = ZERO_ERROR; int offset = (int)(60*60*1000*1.75); // Pick a weird offset SimpleTimeZone zone = new SimpleTimeZone(offset, "TestZone"); if (zone.useDaylightTime()) errln("FAIL: useDaylightTime should return false"); // Establish our expected transition times. Do this with a non-DST // calendar with the (above) declared local offset. GregorianCalendar gc = new GregorianCalendar(zone); gc.clear(); gc.set(1990, Calendar.MARCH, 1); long marchOneStd = gc.getTime().getTime(); // Local Std time midnight gc.clear(); gc.set(1990, Calendar.JULY, 1); long julyOneStd = gc.getTime().getTime(); // Local Std time midnight // Starting and ending hours, WALL TIME int startHour = (int)(2.25 * 3600000); int endHour = (int)(3.5 * 3600000); zone.setStartRule(Calendar.MARCH, 1, 0, startHour); zone.setEndRule (Calendar.JULY, 1, 0, endHour); gc = new GregorianCalendar(zone); // if (failure(status, "new GregorianCalendar")) return; long marchOne = marchOneStd + startHour; long julyOne = julyOneStd + endHour - 3600000; // Adjust from wall to Std time long expMarchOne = 636251400000L; if (marchOne != expMarchOne) { errln("FAIL: Expected start computed as " + marchOne + " = " + new Date(marchOne)); logln(" Should be " + expMarchOne + " = " + new Date(expMarchOne)); } long expJulyOne = 646793100000L; if (julyOne != expJulyOne) { errln("FAIL: Expected start computed as " + julyOne + " = " + new Date(julyOne)); logln(" Should be " + expJulyOne + " = " + new Date(expJulyOne)); } Calendar cal1 = Calendar.getInstance(); cal1.set(1990, Calendar.JANUARY, 1); Calendar cal2 = Calendar.getInstance(); cal2.set(1990, Calendar.JUNE, 1); _testUsingBinarySearch(zone, cal1.getTimeInMillis(), cal2.getTimeInMillis(), marchOne); cal1.set(1990, Calendar.JUNE, 1); cal2.set(1990, Calendar.DECEMBER, 31); _testUsingBinarySearch(zone, cal1.getTimeInMillis(), cal2.getTimeInMillis(), julyOne); if (zone.inDaylightTime(new Date(marchOne - 1000)) || !zone.inDaylightTime(new Date(marchOne))) errln("FAIL: Start rule broken"); if (!zone.inDaylightTime(new Date(julyOne - 1000)) || zone.inDaylightTime(new Date(julyOne))) errln("FAIL: End rule broken"); zone.setStartYear(1991); if (zone.inDaylightTime(new Date(marchOne)) || zone.inDaylightTime(new Date(julyOne - 1000))) errln("FAIL: Start year broken"); // failure(status, "TestRuleAPI"); // delete gc; // delete zone; } void _testUsingBinarySearch(SimpleTimeZone tz, long min, long max, long expectedBoundary) { // ErrorCode status = ZERO_ERROR; boolean startsInDST = tz.inDaylightTime(new Date(min)); // if (failure(status, "SimpleTimeZone::inDaylightTime")) return; if (tz.inDaylightTime(new Date(max)) == startsInDST) { logln("Error: inDaylightTime(" + new Date(max) + ") != " + (!startsInDST)); return; } // if (failure(status, "SimpleTimeZone::inDaylightTime")) return; while ((max - min) > INTERVAL) { long mid = (min + max) / 2; if (tz.inDaylightTime(new Date(mid)) == startsInDST) { min = mid; } else { max = mid; } // if (failure(status, "SimpleTimeZone::inDaylightTime")) return; } logln("Binary Search Before: " + min + " = " + new Date(min)); logln("Binary Search After: " + max + " = " + new Date(max)); long mindelta = expectedBoundary - min; // not used long maxdelta = max - expectedBoundary; if (mindelta >= 0 && mindelta <= INTERVAL && mindelta >= 0 && mindelta <= INTERVAL) logln("PASS: Expected bdry: " + expectedBoundary + " = " + new Date(expectedBoundary)); else errln("FAIL: Expected bdry: " + expectedBoundary + " = " + new Date(expectedBoundary)); } static final int INTERVAL = 100; // Bug 006; verify the offset for a specific zone. @Test public void TestPRTOffset() { TimeZone tz = TimeZone.getTimeZone( "PRT" ); if( tz == null ) { errln( "FAIL: TimeZone(PRT) is null" ); } else{ if (tz.getRawOffset() != (-4*millisPerHour)) warnln("FAIL: Offset for PRT should be -4, got " + tz.getRawOffset() / (double)millisPerHour); } } // Test various calls @Test public void TestVariousAPI518() { TimeZone time_zone = TimeZone.getTimeZone("PST"); Calendar cal = Calendar.getInstance(); cal.set(1997, Calendar.APRIL, 30); Date d = cal.getTime(); logln("The timezone is " + time_zone.getID()); if (time_zone.inDaylightTime(d) != true) errln("FAIL: inDaylightTime returned false"); if (time_zone.useDaylightTime() != true) errln("FAIL: useDaylightTime returned false"); if (time_zone.getRawOffset() != -8*millisPerHour) errln( "FAIL: getRawOffset returned wrong value"); GregorianCalendar gc = new GregorianCalendar(); gc.setTime(d); if (time_zone.getOffset(GregorianCalendar.AD, gc.get(GregorianCalendar.YEAR), gc.get(GregorianCalendar.MONTH), gc.get(GregorianCalendar.DAY_OF_MONTH), gc.get(GregorianCalendar.DAY_OF_WEEK), 0) != -7*millisPerHour) errln("FAIL: getOffset returned wrong value"); } // Test getAvailableID API @Test public void TestGetAvailableIDs913() { StringBuffer buf = new StringBuffer("TimeZone.getAvailableIDs() = { "); String[] s = TimeZone.getAvailableIDs(); for (int i=0; i 0) buf.append(", "); buf.append(s[i]); } buf.append(" };"); logln(buf.toString()); buf.setLength(0); buf.append("TimeZone.getAvailableIDs(GMT+02:00) = { "); s = TimeZone.getAvailableIDs(+2 * 60 * 60 * 1000); for (int i=0; i 0) buf.append(", "); buf.append(s[i]); } buf.append(" };"); logln(buf.toString()); TimeZone tz = TimeZone.getTimeZone("PST"); if (tz != null) logln("getTimeZone(PST) = " + tz.getID()); else errln("FAIL: getTimeZone(PST) = null"); tz = TimeZone.getTimeZone("America/Los_Angeles"); if (tz != null) logln("getTimeZone(America/Los_Angeles) = " + tz.getID()); else errln("FAIL: getTimeZone(PST) = null"); // Bug 4096694 tz = TimeZone.getTimeZone("NON_EXISTENT"); if (tz == null) errln("FAIL: getTimeZone(NON_EXISTENT) = null"); else if (!tz.getID().equals(TimeZone.UNKNOWN_ZONE_ID)) errln("FAIL: getTimeZone(NON_EXISTENT) = " + tz.getID()); } @Test public void TestGetAvailableIDsNew() { Set any = TimeZone.getAvailableIDs(SystemTimeZoneType.ANY, null, null); Set canonical = TimeZone.getAvailableIDs(SystemTimeZoneType.CANONICAL, null, null); Set canonicalLoc = TimeZone.getAvailableIDs(SystemTimeZoneType.CANONICAL_LOCATION, null, null); checkContainsAll(any, "ANY", canonical, "CANONICAL"); checkContainsAll(canonical, "CANONICAL", canonicalLoc, "CANONICALLOC"); Set any_US = TimeZone.getAvailableIDs(SystemTimeZoneType.ANY, "US", null); Set canonical_US = TimeZone.getAvailableIDs(SystemTimeZoneType.CANONICAL, "US", null); Set canonicalLoc_US = TimeZone.getAvailableIDs(SystemTimeZoneType.CANONICAL_LOCATION, "US", null); checkContainsAll(any, "ANY", any_US, "ANY_US"); checkContainsAll(canonical, "CANONICAL", canonical_US, "CANONICAL_US"); checkContainsAll(canonicalLoc, "CANONICALLOC", canonicalLoc_US, "CANONICALLOC_US"); checkContainsAll(any_US, "ANY_US", canonical_US, "CANONICAL_US"); checkContainsAll(canonical_US, "CANONICAL_US", canonicalLoc_US, "CANONICALLOC_US"); final int HOUR = 60*60*1000; Set any_W5 = TimeZone.getAvailableIDs(SystemTimeZoneType.ANY, null, -5 * HOUR); Set any_CA_W5 = TimeZone.getAvailableIDs(SystemTimeZoneType.ANY, "CA", -5 * HOUR); checkContainsAll(any, "ANY", any_W5, "ANY_W5"); checkContainsAll(any_W5, "ANY_W5", any_CA_W5, "ANY_CA_W5"); boolean[] isSystemID = new boolean[1]; // An ID in any set, but not in canonical set must not be a canonical ID for (String id : any) { if (canonical.contains(id)) { continue; } String cid = TimeZone.getCanonicalID(id, isSystemID); if (id.equals(cid)) { errln("FAIL: canonical ID [" + id + "] is not in CANONICAL"); } if (!isSystemID[0]) { errln("FAIL: ANY contains non-system ID: " + id); } } // canonical set must contains only canonical IDs for (String id : canonical) { String cid = TimeZone.getCanonicalID(id, isSystemID); if (!id.equals(cid)) { errln("FAIL: CANONICAL contains non-canonical ID: " + id); } if (!isSystemID[0]) { errln("FAIL: CANONICAL contains non-system ID: " + id); } } // canonicalLoc set must contains only canonical location IDs for (String id : canonicalLoc) { String cid = TimeZone.getCanonicalID(id, isSystemID); if (!id.equals(cid)) { errln("FAIL: CANONICAL contains non-canonical ID: " + id); } if (!isSystemID[0]) { errln("FAIL: CANONICAL contains non-system ID: " + id); } String region = TimeZone.getRegion(id); if (region.equals("001")) { errln("FAIL: CANONICALLOC contains non location zone: " + id); } } // any_US must contain only US zones for (String id : any_US) { String region = TimeZone.getRegion(id); if (!region.equals("US")) { errln("FAIL: ANY_US contains non-US zone ID: " + id); } } // any_W5 must contain only GMT-05:00 zones for (String id : any_W5) { TimeZone tz = TimeZone.getTimeZone(id); if (tz.getRawOffset() != -5 * HOUR) { errln("FAIL: ANY_W5 contains a zone whose offset is not -5:00: " + id); } } // No US zones with GMT+14:00 Set any_US_E14 = TimeZone.getAvailableIDs(SystemTimeZoneType.ANY, "US", 14 * HOUR); if (!any_US_E14.isEmpty()) { errln("FAIL: ANY_US_E14 must be empty"); } } private void checkContainsAll(Set set1, String name1, Set set2, String name2) { if (!set1.containsAll(set2)) { StringBuilder buf = new StringBuilder(); for (String s : set2) { if (!set1.contains(s)) { if (buf.length() != 0) { buf.append(","); } buf.append(s); } } errln("FAIL: " + name1 + " does not contain all of " + name2 + " - missing: {" + buf + "}"); } } /** * Bug 4107276 */ @Test public void TestDSTSavings() { // It might be better to find a way to integrate this test into the main TimeZone // tests above, but I don't have time to figure out how to do this (or if it's // even really a good idea). Let's consider that a future. --rtg 1/27/98 SimpleTimeZone tz = new SimpleTimeZone(-5 * millisPerHour, "dstSavingsTest", Calendar.MARCH, 1, 0, 0, Calendar.SEPTEMBER, 1, 0, 0, (int)(0.5 * millisPerHour)); if (tz.getRawOffset() != -5 * millisPerHour) errln("Got back a raw offset of " + (tz.getRawOffset() / millisPerHour) + " hours instead of -5 hours."); if (!tz.useDaylightTime()) errln("Test time zone should use DST but claims it doesn't."); if (tz.getDSTSavings() != 0.5 * millisPerHour) errln("Set DST offset to 0.5 hour, but got back " + (tz.getDSTSavings() / millisPerHour) + " hours instead."); int offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.JANUARY, 1, Calendar.THURSDAY, 10 * millisPerHour); if (offset != -5 * millisPerHour) errln("The offset for 10 AM, 1/1/98 should have been -5 hours, but we got " + (offset / millisPerHour) + " hours."); offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.JUNE, 1, Calendar.MONDAY, 10 * millisPerHour); if (offset != -4.5 * millisPerHour) errln("The offset for 10 AM, 6/1/98 should have been -4.5 hours, but we got " + (offset / millisPerHour) + " hours."); tz.setDSTSavings(millisPerHour); offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.JANUARY, 1, Calendar.THURSDAY, 10 * millisPerHour); if (offset != -5 * millisPerHour) errln("The offset for 10 AM, 1/1/98 should have been -5 hours, but we got " + (offset / millisPerHour) + " hours."); offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.JUNE, 1, Calendar.MONDAY, 10 * millisPerHour); if (offset != -4 * millisPerHour) errln("The offset for 10 AM, 6/1/98 (with a 1-hour DST offset) should have been -4 hours, but we got " + (offset / millisPerHour) + " hours."); } /** * Bug 4107570 */ @Test public void TestAlternateRules() { // Like TestDSTSavings, this test should probably be integrated somehow with the main // test at the top of this class, but I didn't have time to figure out how to do that. // --rtg 1/28/98 SimpleTimeZone tz = new SimpleTimeZone(-5 * millisPerHour, "alternateRuleTest"); // test the day-of-month API tz.setStartRule(Calendar.MARCH, 10, 12 * millisPerHour); tz.setEndRule(Calendar.OCTOBER, 20, 12 * millisPerHour); int offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.MARCH, 5, Calendar.THURSDAY, 10 * millisPerHour); if (offset != -5 * millisPerHour) errln("The offset for 10AM, 3/5/98 should have been -5 hours, but we got " + (offset / millisPerHour) + " hours."); offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.MARCH, 15, Calendar.SUNDAY, 10 * millisPerHour); if (offset != -4 * millisPerHour) errln("The offset for 10AM, 3/15/98 should have been -4 hours, but we got " + (offset / millisPerHour) + " hours."); offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.OCTOBER, 15, Calendar.THURSDAY, 10 * millisPerHour); if (offset != -4 * millisPerHour) errln("The offset for 10AM, 10/15/98 should have been -4 hours, but we got " + (offset / millisPerHour) + " hours."); offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.OCTOBER, 25, Calendar.SUNDAY, 10 * millisPerHour); if (offset != -5 * millisPerHour) errln("The offset for 10AM, 10/25/98 should have been -5 hours, but we got " + (offset / millisPerHour) + " hours."); // test the day-of-week-after-day-in-month API tz.setStartRule(Calendar.MARCH, 10, Calendar.FRIDAY, 12 * millisPerHour, true); tz.setEndRule(Calendar.OCTOBER, 20, Calendar.FRIDAY, 12 * millisPerHour, false); offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.MARCH, 11, Calendar.WEDNESDAY, 10 * millisPerHour); if (offset != -5 * millisPerHour) errln("The offset for 10AM, 3/11/98 should have been -5 hours, but we got " + (offset / millisPerHour) + " hours."); offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.MARCH, 14, Calendar.SATURDAY, 10 * millisPerHour); if (offset != -4 * millisPerHour) errln("The offset for 10AM, 3/14/98 should have been -4 hours, but we got " + (offset / millisPerHour) + " hours."); offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.OCTOBER, 15, Calendar.THURSDAY, 10 * millisPerHour); if (offset != -4 * millisPerHour) errln("The offset for 10AM, 10/15/98 should have been -4 hours, but we got " + (offset / millisPerHour) + " hours."); offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.OCTOBER, 17, Calendar.SATURDAY, 10 * millisPerHour); if (offset != -5 * millisPerHour) errln("The offset for 10AM, 10/17/98 should have been -5 hours, but we got " + (offset / millisPerHour) + " hours."); } @Test public void TestEquivalencyGroups() { String id = "America/Los_Angeles"; int n = TimeZone.countEquivalentIDs(id); if (n < 2) { errln("FAIL: countEquivalentIDs(" + id + ") returned " + n + ", expected >= 2"); } for (int i=0; i 0) { errln("FAIL: getEquivalentID(" + invld + ", 0) returned \"" + sEquiv0 + "\", expected empty string"); } } } @Test public void TestCountries() { // Make sure America/Los_Angeles is in the "US" group, and // Asia/Tokyo isn't. Vice versa for the "JP" group. String[] s = TimeZone.getAvailableIDs("US"); boolean la = false, tokyo = false; String laZone = "America/Los_Angeles", tokyoZone = "Asia/Tokyo"; for (int i=0; i", " (A zone ID with "Zone" rule)"}, {"Africa/Accra", "Africa/Abidjan"}, {"Africa/Addis_Ababa", "Africa/Nairobi"}, {"Africa/Asmera", "Africa/Nairobi"}, {"Africa/Bamako", "Africa/Abidjan"}, {"Africa/Bangui", "Africa/Lagos"}, {"Africa/Banjul", "Africa/Abidjan"}, {"Africa/Blantyre", "Africa/Maputo"}, {"Africa/Brazzaville", "Africa/Lagos"}, {"Africa/Bujumbura", "Africa/Maputo"}, {"Africa/Conakry", "Africa/Abidjan"}, {"Africa/Dakar", "Africa/Abidjan"}, {"Africa/Dar_es_Salaam", "Africa/Nairobi"}, {"Africa/Djibouti", "Africa/Nairobi"}, {"Africa/Douala", "Africa/Lagos"}, {"Africa/Freetown", "Africa/Abidjan"}, {"Africa/Gaborone", "Africa/Maputo"}, {"Africa/Harare", "Africa/Maputo"}, {"Africa/Kampala", "Africa/Nairobi"}, {"Africa/Khartoum", "Africa/Juba"}, {"Africa/Kigali", "Africa/Maputo"}, {"Africa/Kinshasa", "Africa/Lagos"}, {"Africa/Libreville", "Africa/Lagos"}, {"Africa/Lome", "Africa/Abidjan"}, {"Africa/Luanda", "Africa/Lagos"}, {"Africa/Lubumbashi", "Africa/Maputo"}, {"Africa/Lusaka", "Africa/Maputo"}, {"Africa/Maseru", "Africa/Johannesburg"}, {"Africa/Malabo", "Africa/Lagos"}, {"Africa/Mbabane", "Africa/Johannesburg"}, {"Africa/Mogadishu", "Africa/Nairobi"}, {"Africa/Niamey", "Africa/Lagos"}, {"Africa/Nouakchott", "Africa/Abidjan"}, {"Africa/Ouagadougou", "Africa/Abidjan"}, {"Africa/Porto-Novo", "Africa/Lagos"}, {"Africa/Sao_Tome", "Africa/Abidjan"}, {"America/Antigua", "America/Puerto_Rico"}, {"America/Anguilla", "America/Puerto_Rico"}, {"America/Aruba", "America/Puerto_Rico"}, {"America/Atikokan", "America/Panama"}, {"America/Blanc-Sablon", "America/Puerto_Rico"}, {"America/Cayman", "America/Panama"}, {"America/Coral_Harbour", "America/Panama"}, {"America/Creston", "America/Phoenix"}, {"America/Curacao", "America/Puerto_Rico"}, {"America/Dominica", "America/Puerto_Rico"}, {"America/Grenada", "America/Puerto_Rico"}, {"America/Guadeloupe", "America/Puerto_Rico"}, {"America/Kralendijk", "America/Puerto_Rico"}, {"America/Lower_Princes", "America/Puerto_Rico"}, {"America/Marigot", "America/Puerto_Rico"}, {"America/Montreal", "America/Toronto"}, {"America/Montserrat", "America/Puerto_Rico"}, {"America/Nassau", "America/Toronto"}, {"America/Nipigon", "America/Toronto"}, {"America/Pangnirtung", "America/Iqaluit"}, {"America/Port_of_Spain", "America/Puerto_Rico"}, {"America/Rainy_River", "America/Winnipeg"}, {"America/Santa_Isabel", "America/Tijuana"}, {"America/Shiprock", "America/Denver"}, {"America/St_Barthelemy", "America/Puerto_Rico"}, {"America/St_Kitts", "America/Puerto_Rico"}, {"America/St_Lucia", "America/Puerto_Rico"}, {"America/St_Thomas", "America/Puerto_Rico"}, {"America/St_Vincent", "America/Puerto_Rico"}, {"America/Thunder_Bay", "America/Toronto"}, {"America/Tortola", "America/Puerto_Rico"}, {"America/Virgin", "America/Puerto_Rico"}, {"America/Yellowknife", "America/Edmonton"}, {"Antarctica/DumontDUrville", "Pacific/Port_Moresby"}, {"Antarctica/South_Pole", "Antarctica/McMurdo"}, {"Antarctica/Syowa", "Asia/Riyadh"}, {"Arctic/Longyearbyen", "Europe/Berlin"}, {"Asia/Aden", "Asia/Riyadh"}, {"Asia/Brunei", "Asia/Kuching"}, {"Asia/Kuala_Lumpur", "Asia/Singapore"}, {"Asia/Kuwait", "Asia/Riyadh"}, {"Asia/Muscat", "Asia/Dubai"}, {"Asia/Phnom_Penh", "Asia/Bangkok"}, {"Asia/Qatar", "Asia/Bahrain"}, {"Asia/Vientiane", "Asia/Bangkok"}, {"Atlantic/Jan_Mayen", "Europe/Berlin"}, {"Atlantic/Reykjavik", "Africa/Abidjan"}, {"Atlantic/St_Helena", "Africa/Abidjan"}, {"Australia/Currie", "Australia/Hobart"}, {"Australia/Tasmania", "Australia/Hobart"}, {"Europe/Bratislava", "Europe/Prague"}, {"Europe/Brussels", "Europe/Amsterdam"}, {"Europe/Busingen", "Europe/Zurich"}, {"Europe/Copenhagen", "Europe/Berlin"}, {"Europe/Guernsey", "Europe/London"}, {"Europe/Isle_of_Man", "Europe/London"}, {"Europe/Jersey", "Europe/London"}, {"Europe/Ljubljana", "Europe/Belgrade"}, {"Europe/Luxembourg", "Europe/Amsterdam"}, {"Europe/Mariehamn", "Europe/Helsinki"}, {"Europe/Monaco", "Europe/Paris"}, {"Europe/Oslo", "Europe/Berlin"}, {"Europe/Podgorica", "Europe/Belgrade"}, {"Europe/San_Marino", "Europe/Rome"}, {"Europe/Sarajevo", "Europe/Belgrade"}, {"Europe/Skopje", "Europe/Belgrade"}, {"Europe/Stockholm", "Europe/Berlin"}, {"Europe/Uzhgorod", "Europe/Kiev"}, {"Europe/Vaduz", "Europe/Zurich"}, {"Europe/Vatican", "Europe/Rome"}, {"Europe/Zagreb", "Europe/Belgrade"}, {"Europe/Zaporozhye", "Europe/Kiev"}, {"Indian/Antananarivo", "Africa/Nairobi"}, {"Indian/Christmas", "Asia/Bangkok"}, {"Indian/Cocos", "Asia/Rangoon"}, {"Indian/Comoro", "Africa/Nairobi"}, {"Indian/Mahe", "Asia/Dubai"}, {"Indian/Maldives", "Indian/Kerguelen"}, {"Indian/Mayotte", "Africa/Nairobi"}, {"Indian/Reunion", "Asia/Dubai"}, {"Pacific/Auckland", "Antarctica/McMurdo"}, {"Pacific/Johnston", "Pacific/Honolulu"}, {"Pacific/Majuro", "Pacific/Funafuti"}, {"Pacific/Midway", "Pacific/Pago_Pago"}, {"Pacific/Ponape", "Pacific/Guadalcanal"}, {"Pacific/Saipan", "Pacific/Guam"}, {"Pacific/Tarawa", "Pacific/Funafuti"}, {"Pacific/Truk", "Pacific/Port_Moresby"}, {"Pacific/Wake", "Pacific/Funafuti"}, {"Pacific/Wallis", "Pacific/Funafuti"}, }; // Following IDs are aliases of Etc/GMT in CLDR, // but Olson tzdata has 3 independent definitions // for Etc/GMT, Etc/UTC, Etc/UCT. // Until we merge them into one equivalent group // in zoneinfo.res, we exclude them in the test // below. final String[] excluded2 = { "Etc/UCT", "UCT", "Etc/UTC", "UTC", "Etc/Universal", "Universal", "Etc/Zulu", "Zulu", }; // Walk through equivalency groups String[] ids = TimeZone.getAvailableIDs(); for (int i = 0; i < ids.length; i++) { int nEquiv = TimeZone.countEquivalentIDs(ids[i]); if (nEquiv == 0) { continue; } String canonicalID = null; boolean bFoundCanonical = false; // Make sure getCanonicalID returns the exact same result // for all entries within a same equivalency group with some // exceptions listed in exluded1. // Also, one of them must be canonical id. for (int j = 0; j < nEquiv; j++) { String tmp = TimeZone.getEquivalentID(ids[i], j); String tmpCanonical = TimeZone.getCanonicalID(tmp); if (tmpCanonical == null) { errln("FAIL: getCanonicalID(\"" + tmp + "\") returned null"); continue; } // Some exceptional cases for (int k = 0; k < excluded1.length; k++) { if (tmpCanonical.equals(excluded1[k][0])) { tmpCanonical = excluded1[k][1]; } } if (j == 0) { canonicalID = tmpCanonical; } else if (!canonicalID.equals(tmpCanonical)) { errln("FAIL: getCanonicalID(\"" + tmp + "\") returned " + tmpCanonical + " expected:" + canonicalID); } if (canonicalID.equals(tmp)) { bFoundCanonical = true; } } // At least one ID in an equvalency group must match the // canonicalID if (!bFoundCanonical) { // test exclusion because of differences between Olson tzdata and CLDR boolean isExcluded = false; for (int k = 0; k < excluded2.length; k++) { if (ids[i].equals(excluded2[k])) { isExcluded = true; break; } } if (isExcluded) { continue; } errln("FAIL: No timezone ids match the canonical ID " + canonicalID); } } // Testing some special cases final String[][] data = { {"GMT-03", "GMT-03:00", null}, {"GMT+4", "GMT+04:00", null}, {"GMT-055", "GMT-00:55", null}, {"GMT+430", "GMT+04:30", null}, {"GMT-12:15", "GMT-12:15", null}, {"GMT-091015", "GMT-09:10:15", null}, {"GMT+1:90", null, null}, {"America/Argentina/Buenos_Aires", "America/Buenos_Aires", "true"}, {"Etc/Unknown", "Etc/Unknown", null}, {"bogus", null, null}, {"", null, null}, {"America/Marigot", "America/Marigot", "true"}, // Olson link, but CLDR canonical (#8953) {"Europe/Bratislava", "Europe/Bratislava", "true"}, // Same as above {null, null, null}, }; boolean[] isSystemID = new boolean[1]; for (int i = 0; i < data.length; i++) { String canonical = TimeZone.getCanonicalID(data[i][0], isSystemID); if (canonical != null && !canonical.equals(data[i][1]) || canonical == null && data[i][1] != null) { errln("FAIL: getCanonicalID(\"" + data[i][0] + "\") returned " + canonical + " - expected: " + data[i][1]); } if ("true".equalsIgnoreCase(data[i][2]) != isSystemID[0]) { errln("FAIL: getCanonicalID(\"" + data[i][0] + "\") set " + isSystemID[0] + " to isSystemID"); } } } @Test public void TestSetDefault() { java.util.TimeZone save = java.util.TimeZone.getDefault(); TimeZone icuSave = TimeZone.getDefault(); /* * America/Caracs (Venezuela) changed the base offset from -4:00 to * -4:30 on Dec 9, 2007. */ TimeZone icuCaracas = TimeZone.getTimeZone("America/Caracas", TimeZone.TIMEZONE_ICU); java.util.TimeZone jdkCaracas = java.util.TimeZone.getTimeZone("America/Caracas"); // Set JDK America/Caracas as the default java.util.TimeZone.setDefault(jdkCaracas); java.util.Calendar jdkCal = java.util.Calendar.getInstance(); jdkCal.clear(); jdkCal.set(2007, java.util.Calendar.JANUARY, 1); int rawOffset = jdkCal.get(java.util.Calendar.ZONE_OFFSET); int dstSavings = jdkCal.get(java.util.Calendar.DST_OFFSET); int[] offsets = new int[2]; icuCaracas.getOffset(jdkCal.getTime().getTime()/*jdkCal.getTimeInMillis()*/, false, offsets); boolean isTimeZoneSynchronized = true; if (rawOffset != offsets[0] || dstSavings != offsets[1]) { // JDK time zone rule is out of sync... logln("Rule for JDK America/Caracas is not same with ICU. Skipping the rest."); isTimeZoneSynchronized = false; } if (isTimeZoneSynchronized) { // If JDK America/Caracas uses the same rule with ICU, // the following code should work well. TimeZone.setDefault(icuCaracas); // Create a new JDK calendar instance again. // This calendar should reflect the new default // set by ICU TimeZone#setDefault. jdkCal = java.util.Calendar.getInstance(); jdkCal.clear(); jdkCal.set(2007, java.util.Calendar.JANUARY, 1); rawOffset = jdkCal.get(java.util.Calendar.ZONE_OFFSET); dstSavings = jdkCal.get(java.util.Calendar.DST_OFFSET); if (rawOffset != offsets[0] || dstSavings != offsets[1]) { errln("ERROR: Got offset [raw:" + rawOffset + "/dst:" + dstSavings + "] Expected [raw:" + offsets[0] + "/dst:" + offsets[1] + "]"); } } // Restore the original JDK time zone TimeZone.setDefault(icuSave); java.util.TimeZone.setDefault(save); } /* * Test Display Names, choosing zones and lcoales where there are multiple * meta-zones defined. */ @Test public void TestDisplayNamesMeta() { final Integer TZSHORT = TimeZone.SHORT; final Integer TZLONG = TimeZone.LONG; final Object[][] zoneDisplayTestData = { // zone id locale summer format expected display name {"Europe/London", "en", Boolean.FALSE, TZSHORT, "GMT"}, {"Europe/London", "en", Boolean.FALSE, TZLONG, "Greenwich Mean Time"}, {"Europe/London", "en", Boolean.TRUE, TZSHORT, "GMT+1" /*"BST"*/}, {"Europe/London", "en", Boolean.TRUE, TZLONG, "British Summer Time"}, {"America/Anchorage", "en", Boolean.FALSE, TZSHORT, "AKST"}, {"America/Anchorage", "en", Boolean.FALSE, TZLONG, "Alaska Standard Time"}, {"America/Anchorage", "en", Boolean.TRUE, TZSHORT, "AKDT"}, {"America/Anchorage", "en", Boolean.TRUE, TZLONG, "Alaska Daylight Time"}, // Southern Hemisphere, all data from meta:Australia_Western {"Australia/Perth", "en", Boolean.FALSE, TZSHORT, "GMT+8"/*"AWST"*/}, {"Australia/Perth", "en", Boolean.FALSE, TZLONG, "Australian Western Standard Time"}, // Note: Perth does not observe DST currently. When display name is missing, // the localized GMT format with the current offset is used even daylight name was // requested. See #9350. {"Australia/Perth", "en", Boolean.TRUE, TZSHORT, "GMT+8"/*"AWDT"*/}, {"Australia/Perth", "en", Boolean.TRUE, TZLONG, "Australian Western Daylight Time"}, {"America/Sao_Paulo", "en", Boolean.FALSE, TZSHORT, "GMT-3"/*"BRT"*/}, {"America/Sao_Paulo", "en", Boolean.FALSE, TZLONG, "Brasilia Standard Time"}, // Per https://mm.icann.org/pipermail/tz-announce/2019-July/000056.html // Brazil has canceled DST and will stay on standard time indefinitely. // {"America/Sao_Paulo", "en", Boolean.TRUE, TZSHORT, "GMT-2"/*"BRST"*/}, // {"America/Sao_Paulo", "en", Boolean.TRUE, TZLONG, "Brasilia Summer Time"}, // No Summer Time, but had it before 1983. {"Pacific/Honolulu", "en", Boolean.FALSE, TZSHORT, "HST"}, {"Pacific/Honolulu", "en", Boolean.FALSE, TZLONG, "Hawaii-Aleutian Standard Time"}, {"Pacific/Honolulu", "en", Boolean.TRUE, TZSHORT, "HDT"}, {"Pacific/Honolulu", "en", Boolean.TRUE, TZLONG, "Hawaii-Aleutian Daylight Time"}, // Northern, has Summer, not commonly used. {"Europe/Helsinki", "en", Boolean.FALSE, TZSHORT, "GMT+2"/*"EET"*/}, {"Europe/Helsinki", "en", Boolean.FALSE, TZLONG, "Eastern European Standard Time"}, {"Europe/Helsinki", "en", Boolean.TRUE, TZSHORT, "GMT+3"/*"EEST"*/}, {"Europe/Helsinki", "en", Boolean.TRUE, TZLONG, "Eastern European Summer Time"}, // Repeating the test data for DST. The test data below trigger the problem reported // by Ticket#6644 {"Europe/London", "en", Boolean.TRUE, TZSHORT, "GMT+1" /*"BST"*/}, {"Europe/London", "en", Boolean.TRUE, TZLONG, "British Summer Time"}, }; boolean isICUTimeZone = (TimeZone.getDefaultTimeZoneType() == TimeZone.TIMEZONE_ICU); boolean sawAnError = false; for (int testNum = 0; testNum < zoneDisplayTestData.length; testNum++) { ULocale locale = new ULocale((String)zoneDisplayTestData[testNum][1]); TimeZone zone = TimeZone.getTimeZone((String)zoneDisplayTestData[testNum][0]); String displayName = zone.getDisplayName(((Boolean)zoneDisplayTestData[testNum][2]).booleanValue(), ((Integer)zoneDisplayTestData[testNum][3]).intValue()); if (!displayName.equals(zoneDisplayTestData[testNum][4])) { if (isDevelopmentBuild && (isICUTimeZone || !((Boolean)zoneDisplayTestData[testNum][2]).booleanValue())) { sawAnError = true; errln("Incorrect time zone display name. zone = " + zoneDisplayTestData[testNum][0] + ",\n" + " locale = " + locale + ", style = " + (zoneDisplayTestData[testNum][3] == TZSHORT ? "SHORT" : "LONG") + ", Summertime = " + zoneDisplayTestData[testNum][2] + "\n" + " Expected " + zoneDisplayTestData[testNum][4] + ", Got " + displayName); } else { logln("Incorrect time zone display name. zone = " + zoneDisplayTestData[testNum][0] + ",\n" + " locale = " + locale + ", style = " + (zoneDisplayTestData[testNum][3] == TZSHORT ? "SHORT" : "LONG") + ", Summertime = " + zoneDisplayTestData[testNum][2] + "\n" + " Expected " + zoneDisplayTestData[testNum][4] + ", Got " + displayName); } } } if (sawAnError) { logln("Note: Errors could be the result of changes to zoneStrings locale data"); } } /* * Test case for hashCode problem reported by ticket#7690 OlsonTimeZone.hashCode() throws NPE. */ @Test public void TestHashCode() { String[] ids = TimeZone.getAvailableIDs(); for (String id: ids) { TimeZone tz1 = TimeZone.getTimeZone(id); TimeZone tz2 = TimeZone.getTimeZone(id); // hash code are same for the same time zone if (tz1.hashCode() != tz2.hashCode()) { errln("Fail: Two time zone instances for " + id + " have different hash values."); } // string representation should be also same if (!tz1.toString().equals(tz2.toString())) { errln("Fail: Two time zone instances for " + id + " have different toString() values."); } } } /* * Test case for getRegion */ @Test public void TestGetRegion() { final String[][] TEST_DATA = { {"America/Los_Angeles", "US"}, {"America/Indianapolis", "US"}, // CLDR canonical, Olson backward {"America/Indiana/Indianapolis", "US"}, // CLDR alias {"Mexico/General", "MX"}, // Link America/Mexico_City, Olson backward {"Etc/UTC", "001"}, {"EST5EDT", "001"}, {"PST", "US"}, // Link America/Los_Angeles {"Europe/Helsinki", "FI"}, {"Europe/Mariehamn", "AX"}, // Link Europe/Helsinki, but in zone.tab {"Asia/Riyadh", "SA"}, // tz file solar87 was removed from tzdata2013i // {"Asia/Riyadh87", "001"}, // this should be "SA" actually, but not in zone.tab {"Atlantic/Jan_Mayen", "SJ"}, {"Pacific/Truk", "FM"}, {"Etc/Unknown", null}, // CLDR canonical, but not a sysmte zone ID {"bogus", null}, // bogus {"GMT+08:00", null}, // a custom ID, not a system zone ID }; for (String[] test : TEST_DATA) { try { String region = TimeZone.getRegion(test[0]); if (!region.equals(test[1])) { if (test[1] == null) { errln("Fail: getRegion(\"" + test[0] + "\") returns " + region + " [expected: IllegalArgumentException]"); } else { errln("Fail: getRegion(\"" + test[0] + "\") returns " + region + " [expected: " + test[1] + "]"); } } } catch (IllegalArgumentException e) { if (test[1] != null) { errln("Fail: getRegion(\"" + test[0] + "\") throws IllegalArgumentException [expected: " + test[1] + "]"); } } } } @Test public void TestZoneFields() { assertEquals("UNKNOWN_ZONE wrong ID", "Etc/Unknown", TimeZone.UNKNOWN_ZONE.getID()); assertEquals("UNKNOWN_ZONE wrong offset", 0, TimeZone.UNKNOWN_ZONE.getRawOffset()); assertFalse("UNKNOWN_ZONE uses DST", TimeZone.UNKNOWN_ZONE.useDaylightTime()); assertEquals("GMT_ZONE wrong ID", "Etc/GMT", TimeZone.GMT_ZONE.getID()); assertEquals("GMT_ZONE wrong offset", 0, TimeZone.GMT_ZONE.getRawOffset()); assertFalse("GMT_ZONE uses DST", TimeZone.GMT_ZONE.useDaylightTime()); } /* * Test case for Freezable */ @Test public void TestFreezable() { // Test zones - initially thawed TimeZone[] ZA1 = { TimeZone.getDefault(), TimeZone.getTimeZone("America/Los_Angeles", TimeZone.TIMEZONE_ICU), TimeZone.getTimeZone("America/Los_Angeles", TimeZone.TIMEZONE_JDK), new SimpleTimeZone(0, "stz"), new RuleBasedTimeZone("rbtz", new InitialTimeZoneRule("rbtz0", 0, 0)), VTimeZone.create("America/New_York"), }; checkThawed(ZA1, "ZA1"); // freeze for (int i = 0; i < ZA1.length; i++) { ZA1[i].freeze(); } checkFrozen(ZA1, "ZA1(frozen)"); // Test zones - initially frozen final TimeZone[] ZA2 = { TimeZone.GMT_ZONE, TimeZone.UNKNOWN_ZONE, TimeZone.getFrozenTimeZone("America/Los_Angeles"), new SimpleTimeZone(3600000, "frz_stz").freeze(), new RuleBasedTimeZone("frz_rbtz", new InitialTimeZoneRule("frz_rbtz0", 3600000, 0)).freeze(), VTimeZone.create("Asia/Tokyo").freeze(), }; checkFrozen(ZA2, "ZA2"); TimeZone[] ZA2_thawed = new TimeZone[ZA2.length]; // create thawed clone for (int i = 0; i < ZA2_thawed.length; i++) { ZA2_thawed[i] = ZA2[i].cloneAsThawed(); } checkThawed(ZA2_thawed, "ZA2(thawed)"); } private void checkThawed(TimeZone[] thawedZones, String zaName) { for (int i = 0; i < thawedZones.length; i++) { if (thawedZones[i].isFrozen()) { errln("Fail: " + zaName + "[" + i + "] is frozen."); } // clone TimeZone copy = (TimeZone)thawedZones[i].clone(); if (thawedZones[i] == copy || !thawedZones[i].equals(copy)) { errln("Fail: " + zaName + "[" + i + "] - clone does not work."); } // cloneAsThawed TimeZone thawed = thawedZones[i].cloneAsThawed(); if (thawed.isFrozen() || !thawedZones[i].equals(thawed)) { errln("Fail: " + zaName + "[" + i + "] - cloneAsThawed does not work."); } // setID try { String newID = "foo"; thawedZones[i].setID(newID); if (!thawedZones[i].getID().equals(newID)) { errln("Fail: " + zaName + "[" + i + "] - setID(\"" + newID + "\") does not work."); } } catch (UnsupportedOperationException e) { errln("Fail: " + zaName + "[" + i + "] - setID throws UnsupportedOperationException."); } // setRawOffset if (!(thawedZones[i] instanceof RuleBasedTimeZone)) { // RuleBasedTimeZone does not support setRawOffset try { int newOffset = -3600000; thawedZones[i].setRawOffset(newOffset); if (thawedZones[i].getRawOffset() != newOffset) { errln("Fail: " + zaName + "[" + i + "] - setRawOffset(" + newOffset + ") does not work."); } } catch (UnsupportedOperationException e) { errln("Fail: " + zaName + "[" + i + "] - setRawOffset throws UnsupportedOperationException."); } } if (thawedZones[i] instanceof SimpleTimeZone) { SimpleTimeZone stz = (SimpleTimeZone)thawedZones[i]; // setDSTSavings try { int newDSTSavings = 1800000; stz.setDSTSavings(newDSTSavings); if (stz.getDSTSavings() != newDSTSavings) { errln("Fail: (SimpleTimeZone)" + zaName + "[" + i + "] - setDSTSavings(" + newDSTSavings + ") does not work."); } } catch (UnsupportedOperationException e) { errln("Fail: (SimpleTimeZone)" + zaName + "[" + i + "] - setDSTSavings throws UnsupportedOperationException."); } // setStartRule try { stz.setStartRule(Calendar.JANUARY, -1, Calendar.SUNDAY, 0); } catch (UnsupportedOperationException e) { errln("Fail: (SimpleTimeZone)" + zaName + "[" + i + "] - setStartRule throws UnsupportedOperationException."); } // setEndRule try { stz.setEndRule(Calendar.DECEMBER, 1, Calendar.SUNDAY, 0); } catch (UnsupportedOperationException e) { errln("Fail: (SimpleTimeZone)" + zaName + "[" + i + "] - setEndRule throws UnsupportedOperationException."); } // setStartYear try { stz.setStartYear(2000); } catch (UnsupportedOperationException e) { errln("Fail: (SimpleTimeZone)" + zaName + "[" + i + "] - setStartYear throws UnsupportedOperationException."); } } else if (thawedZones[i] instanceof RuleBasedTimeZone) { RuleBasedTimeZone rbtz = (RuleBasedTimeZone)thawedZones[i]; // addTransitionRule try { TimeArrayTimeZoneRule tr1 = new TimeArrayTimeZoneRule("tr1", 7200000, 0, new long[] {0}, DateTimeRule.UTC_TIME); rbtz.addTransitionRule(tr1); } catch (UnsupportedOperationException e) { errln("Fail: (RuleBasedTimeZone)" + zaName + "[" + i + "] - addTransitionRule throws UnsupportedOperationException."); } } else if (thawedZones[i] instanceof VTimeZone) { VTimeZone vtz = (VTimeZone)thawedZones[i]; // setTZURL try { String tzUrl = "http://icu-project.org/timezone"; vtz.setTZURL(tzUrl); if (!vtz.getTZURL().equals(tzUrl)) { errln("Fail: (VTimeZone)" + zaName + "[" + i + "] - setTZURL does not work."); } } catch (UnsupportedOperationException e) { errln("Fail: (VTimeZone)" + zaName + "[" + i + "] - setTZURL throws UnsupportedOperationException."); } // setLastModified try { Date d = new Date(); vtz.setLastModified(d); if (!vtz.getLastModified().equals(d)) { errln("Fail: (VTimeZone)" + zaName + "[" + i + "] - setLastModified does not work."); } } catch (UnsupportedOperationException e) { errln("Fail: (VTimeZone)" + zaName + "[" + i + "] - setLastModified throws UnsupportedOperationException."); } } } } private void checkFrozen(TimeZone[] frozenZones, String zaName) { for (int i = 0; i < frozenZones.length; i++) { if (!frozenZones[i].isFrozen()) { errln("Fail: " + zaName + "[" + i + "] is not frozen."); } // clone TimeZone copy = (TimeZone)frozenZones[i].clone(); if (frozenZones[i] != copy) { errln("Fail: " + zaName + "[" + i + "] - clone does not return the object itself."); } // cloneAsThawed TimeZone thawed = frozenZones[i].cloneAsThawed(); if (thawed.isFrozen() || !frozenZones[i].equals(thawed)) { errln("Fail: " + zaName + "[" + i + "] - cloneAsThawed does not work."); } // setID try { String newID = "foo"; frozenZones[i].setID(newID); errln("Fail: " + zaName + "[" + i + "] - setID must throw UnsupportedOperationException."); } catch (UnsupportedOperationException e) { // OK } // setRawOffset if (!(frozenZones[i] instanceof RuleBasedTimeZone)) { // RuleBasedTimeZone does not support setRawOffset try { int newOffset = -3600000; frozenZones[i].setRawOffset(newOffset); errln("Fail: " + zaName + "[" + i + "] - setRawOffset must throw UnsupportedOperationException."); } catch (UnsupportedOperationException e) { // OK } } if (frozenZones[i] instanceof SimpleTimeZone) { SimpleTimeZone stz = (SimpleTimeZone)frozenZones[i]; // setDSTSavings try { int newDSTSavings = 1800000; stz.setDSTSavings(newDSTSavings); errln("Fail: (SimpleTimeZone)" + zaName + "[" + i + "] - setDSTSavings must throw UnsupportedOperationException."); } catch (UnsupportedOperationException e) { // OK } // setStartRule try { stz.setStartRule(Calendar.JANUARY, -1, Calendar.SUNDAY, 0); errln("Fail: (SimpleTimeZone)" + zaName + "[" + i + "] - setStartRule must throw UnsupportedOperationException."); } catch (UnsupportedOperationException e) { // OK } // setEndRule try { stz.setEndRule(Calendar.DECEMBER, 1, Calendar.SUNDAY, 0); errln("Fail: (SimpleTimeZone)" + zaName + "[" + i + "] - setEndRule must throw UnsupportedOperationException."); } catch (UnsupportedOperationException e) { // OK } // setStartYear try { stz.setStartYear(2000); errln("Fail: (SimpleTimeZone)" + zaName + "[" + i + "] - setStartYear must throw UnsupportedOperationException."); } catch (UnsupportedOperationException e) { // OK } } else if (frozenZones[i] instanceof RuleBasedTimeZone) { RuleBasedTimeZone rbtz = (RuleBasedTimeZone)frozenZones[i]; // addTransitionRule try { TimeArrayTimeZoneRule tr1 = new TimeArrayTimeZoneRule("tr1", 7200000, 0, new long[] {0}, DateTimeRule.UTC_TIME); rbtz.addTransitionRule(tr1); errln("Fail: (RuleBasedTimeZone)" + zaName + "[" + i + "] - addTransitionRule must throw UnsupportedOperationException."); } catch (UnsupportedOperationException e) { // OK } } else if (frozenZones[i] instanceof VTimeZone) { VTimeZone vtz = (VTimeZone)frozenZones[i]; // setTZURL try { String tzUrl = "http://icu-project.org/timezone"; vtz.setTZURL(tzUrl); errln("Fail: (VTimeZone)" + zaName + "[" + i + "] - setTZURL must throw UnsupportedOperationException."); } catch (UnsupportedOperationException e) { // OK } // setLastModified try { Date d = new Date(); vtz.setLastModified(d); errln("Fail: (VTimeZone)" + zaName + "[" + i + "] - setLastModified must throw UnsupportedOperationException."); } catch (UnsupportedOperationException e) { // OK } } } } @Test public void TestObservesDaylightTime() { boolean observesDaylight; long current = System.currentTimeMillis(); String[] tzids = TimeZone.getAvailableIDs(); for (String tzid : tzids) { // OlsonTimeZone TimeZone tz = TimeZone.getTimeZone(tzid, TimeZone.TIMEZONE_ICU); observesDaylight = tz.observesDaylightTime(); if (observesDaylight != isDaylightTimeAvailable(tz, current)) { errln("Fail: [OlsonTimeZone] observesDaylightTime() returned " + observesDaylight + " for " + tzid); } // RuleBasedTimeZone RuleBasedTimeZone rbtz = createRBTZ((BasicTimeZone)tz, current); boolean observesDaylightRBTZ = rbtz.observesDaylightTime(); if (observesDaylightRBTZ != isDaylightTimeAvailable(rbtz, current)) { errln("Fail: [RuleBasedTimeZone] observesDaylightTime() returned " + observesDaylightRBTZ + " for " + rbtz.getID()); } else if (observesDaylight != observesDaylightRBTZ) { errln("Fail: RuleBasedTimeZone " + rbtz.getID() + " returns " + observesDaylightRBTZ + ", but different from match OlsonTimeZone"); } // JavaTimeZone tz = TimeZone.getTimeZone(tzid, TimeZone.TIMEZONE_JDK); observesDaylight = tz.observesDaylightTime(); if (observesDaylight != isDaylightTimeAvailable(tz, current)) { errln("Fail: [JavaTimeZone] observesDaylightTime() returned " + observesDaylight + " for " + tzid); } // VTimeZone tz = VTimeZone.getTimeZone(tzid); observesDaylight = tz.observesDaylightTime(); if (observesDaylight != isDaylightTimeAvailable(tz, current)) { errln("Fail: [VTimeZone] observesDaylightTime() returned " + observesDaylight + " for " + tzid); } } // SimpleTimeZone SimpleTimeZone[] stzs = { new SimpleTimeZone(0, "STZ0"), new SimpleTimeZone(-5*60*60*1000, "STZ-5D", Calendar.MARCH, 2, Calendar.SUNDAY, 2*60*60*1000, Calendar.NOVEMBER, 1, Calendar.SUNDAY, 2*60*60*1000), }; for (SimpleTimeZone stz : stzs) { observesDaylight = stz.observesDaylightTime(); if (observesDaylight != isDaylightTimeAvailable(stz, current)) { errln("Fail: [SimpleTimeZone] observesDaylightTime() returned " + observesDaylight + " for " + stz.getID()); } } } @Test public void Test11619_UnrecognizedTimeZoneID() { VTimeZone vzone = VTimeZone.create("ABadTimeZoneId"); TestFmwk.assertNull("", vzone); } private static boolean isDaylightTimeAvailable(TimeZone tz, long start) { if (tz.inDaylightTime(new Date(start))) { return true; } long date; if (tz instanceof BasicTimeZone) { BasicTimeZone btz = (BasicTimeZone)tz; // check future transitions, up to 100 date = start; for (int i = 0; i < 100; i++) { TimeZoneTransition tzt = btz.getNextTransition(date, false); if (tzt == null) { // no more transitions break; } if (tzt.getTo().getDSTSavings() != 0) { return true; } date = tzt.getTime(); } } else { // check future times by incrementing 30 days, up to 200 times (about 16 years) final long inc = 30L * 24 * 60 * 60 * 1000; int[] offsets = new int[2]; date = start + inc; for (int i = 0; i < 200; i++, date += inc) { tz.getOffset(date, false, offsets); if (offsets[1] != 0) { return true; } } } return false; } private static RuleBasedTimeZone createRBTZ(BasicTimeZone btz, long start) { TimeZoneRule[] rules = btz.getTimeZoneRules(start); RuleBasedTimeZone rbtz = new RuleBasedTimeZone("RBTZ:btz.getID()", (InitialTimeZoneRule)rules[0]); for (int i = 1; i < rules.length; i++) { rbtz.addTransitionRule(rules[i]); } return rbtz; } @Test public void TestGetWindowsID() { String[][] TESTDATA = { {"America/New_York", "Eastern Standard Time"}, {"America/Montreal", "Eastern Standard Time"}, {"America/Los_Angeles", "Pacific Standard Time"}, {"America/Vancouver", "Pacific Standard Time"}, {"Asia/Shanghai", "China Standard Time"}, {"Asia/Chongqing", "China Standard Time"}, {"America/Indianapolis", "US Eastern Standard Time"}, // CLDR canonical name {"America/Indiana/Indianapolis", "US Eastern Standard Time"}, // tzdb canonical name {"Asia/Khandyga", "Yakutsk Standard Time"}, {"Australia/Eucla", "Aus Central W. Standard Time"}, // Now Windows does have a mapping {"Bogus", null}, }; for (String[] data : TESTDATA) { String winID = TimeZone.getWindowsID(data[0]); assertEquals("Fail: ID=" + data[0], data[1], winID); } } @Test public void TestGetIDForWindowsID() { final String[][] TESTDATA = { {"Eastern Standard Time", null, "America/New_York"}, {"Eastern Standard Time", "US", "America/New_York"}, {"Eastern Standard Time", "CA", "America/Toronto"}, {"Eastern Standard Time", "CN", "America/New_York"}, {"China Standard Time", null, "Asia/Shanghai"}, {"China Standard Time", "CN", "Asia/Shanghai"}, {"China Standard Time", "HK", "Asia/Hong_Kong"}, {"Mid-Atlantic Standard Time", null, null}, // No tz database mapping {"Bogus", null, null}, }; for (String[] data : TESTDATA) { String id = TimeZone.getIDForWindowsID(data[0], data[1]); assertEquals("Fail: Windows ID=" + data[0] + ", Region=" + data[1], data[2], id); } } @Test public void TestTimeZoneAdapterEquals() { String idChicago = "America/Chicago"; TimeZone icuChicago = TimeZone.getTimeZone(idChicago); TimeZone icuChicago2 = TimeZone.getTimeZone(idChicago); java.util.TimeZone icuChicagoWrapped = TimeZoneAdapter.wrap(icuChicago); java.util.TimeZone icuChicagoWrapped2 = TimeZoneAdapter.wrap(icuChicago2); assertFalse("Compare TimeZone and TimeZoneAdapter", icuChicago.equals(icuChicagoWrapped)); assertFalse("Compare TimeZoneAdapter with TimeZone", icuChicagoWrapped.equals(icuChicago)); assertTrue("Compare two TimeZoneAdapters", icuChicagoWrapped.equals(icuChicagoWrapped2)); } @Test public void TestCasablancaNameAndOffset22041() { String id = "Africa/Casablanca"; TimeZone zone = TimeZone.getTimeZone(id); String standardName = zone.getDisplayName(false, TimeZone.LONG, Locale.ENGLISH); String summerName = zone.getDisplayName(true, TimeZone.LONG, Locale.ENGLISH); assertEquals("TimeZone name for Africa/Casablanca should not contain '+02' since it is located in UTC, but got " + standardName, -1, standardName.indexOf("+02")); assertEquals("TimeZone name for Africa/Casablanca should not contain '+02' since it is located in UTC, but got " + summerName, -1, summerName.indexOf("+02")); int[] offsets = new int[2]; // raw = offsets[0], dst = offsets[1] zone.getOffset((new Date()).getTime(), false, offsets); int raw = offsets[0]; assertEquals("getRawOffset() and the raw from getOffset(now, false, offset) should not be different but got", zone.getRawOffset(), raw); } @Test public void TestRawOffsetAndOffsetConsistency22041() { long now = (new Date()).getTime(); int[] offsets = new int[2]; // raw = offsets[0], dst = offsets[1] for (String id : TimeZone.getAvailableIDs()) { TimeZone zone = TimeZone.getTimeZone(id); zone.getOffset((new Date()).getTime(), false, offsets); int raw = offsets[0]; assertEquals("getRawOffset() and the raw from getOffset(now, false, offset) should not be different but got", zone.getRawOffset(), raw); } } @Test public void TestGetIanaID() { final String UNKNOWN = TimeZone.UNKNOWN_ZONE_ID; final String[][] TESTDATA = { {"", UNKNOWN}, {null, UNKNOWN}, {UNKNOWN, UNKNOWN}, {"America/New_York", "America/New_York"}, {"Asia/Calcutta", "Asia/Kolkata"}, {"Europe/Kiev", "Europe/Kyiv"}, {"Europe/Zaporozhye", "Europe/Kyiv"}, {"Etc/GMT-1", "Etc/GMT-1"}, {"Etc/GMT+20", UNKNOWN}, {"PST8PDT", "PST8PDT"}, {"GMT-08:00", UNKNOWN}, }; for (String[] test : TESTDATA) { String ianaId = TimeZone.getIanaID(test[0]); assertEquals("IANA ID for " + test[0], test[1], ianaId); if (test[1].equals(UNKNOWN)) { // Calling getIanaID with an IANA ID should return the same String ianaId2 = TimeZone.getIanaID(ianaId); assertEquals("IANA ID for " + ianaId, ianaId, ianaId2); } } } @Test public void TestGMTMinus24ICU22526() { TimeZone tz = TimeZone.getTimeZone("GMT-23:59"); GregorianCalendar gc = new GregorianCalendar(tz); gc.setTimeInMillis(123456789); gc.get(GregorianCalendar.MONTH); } } //eof