| // © 2016 and later: Unicode, Inc. and others. |
| // License & terms of use: http://www.unicode.org/copyright.html |
| /* |
| ******************************************************************************* |
| * Copyright (C) 2008-2015, International Business Machines Corporation and * |
| * others. All Rights Reserved. * |
| ******************************************************************************* |
| */ |
| package com.ibm.icu.dev.test.localespi; |
| |
| import java.util.Collections; |
| import java.util.HashSet; |
| import java.util.Locale; |
| import java.util.Set; |
| import java.util.TimeZone; |
| |
| import org.junit.Test; |
| import org.junit.runner.RunWith; |
| import org.junit.runners.JUnit4; |
| |
| import com.ibm.icu.dev.test.TestFmwk; |
| import com.ibm.icu.text.TimeZoneNames; |
| import com.ibm.icu.text.TimeZoneNames.NameType; |
| import com.ibm.icu.util.ULocale; |
| |
| @RunWith(JUnit4.class) |
| public class TimeZoneNameTest extends TestFmwk { |
| |
| private static final Set<String> ProblematicZones = new HashSet<String>(); |
| static { |
| // Since tzdata2013e, Pacific/Johnston is defined as below: |
| // |
| // Link Pacific/Honolulu Pacific/Johnston |
| // |
| // JDK TimeZone.getDisplayName no longer passes Pacific/Johnston to a |
| // TimeZoneNameProvider implementation. As of CLDR 25M1, Pacific/Johnston |
| // has a different set of names from Pacific/Honolulu. This test case |
| // expects JRE calls a TimeZoneNameProvider without such normalization |
| // (and I believe it's a JDK bug). For now, we ignore the test failure |
| // caused by Pacific/Johnston with this the JDK problem. |
| ProblematicZones.add("Pacific/Johnston"); |
| } |
| |
| @Test |
| public void TestTimeZoneNames() { |
| Locale[] locales = Locale.getAvailableLocales(); |
| String[] tzids = TimeZone.getAvailableIDs(); |
| |
| for (Locale loc : locales) { |
| boolean warningOnly = false; |
| if (TestUtil.isExcluded(loc)) { |
| warningOnly = true; |
| } |
| |
| for (String tzid : tzids) { |
| // Java has a problem when a provider does not supply all 4 names |
| // for a zone. For this reason, ICU TimeZoneName provider does not return |
| // localized names unless these 4 names are available. |
| |
| String icuStdLong = getIcuDisplayName(tzid, false, TimeZone.LONG, loc); |
| String icuDstLong = getIcuDisplayName(tzid, true, TimeZone.LONG, loc); |
| String icuStdShort = getIcuDisplayName(tzid, false, TimeZone.SHORT, loc); |
| String icuDstShort = getIcuDisplayName(tzid, true, TimeZone.SHORT, loc); |
| |
| if (icuStdLong != null && icuDstLong != null && icuStdShort != null && icuDstShort != null) { |
| checkDisplayNamePair(TimeZone.SHORT, tzid, loc, warningOnly || ProblematicZones.contains(tzid)); |
| checkDisplayNamePair(TimeZone.LONG, tzid, loc, warningOnly || ProblematicZones.contains(tzid)); |
| } else { |
| logln("Localized long standard name is not available for " |
| + tzid + " in locale " + loc + " in ICU"); |
| } |
| } |
| } |
| } |
| |
| private void checkDisplayNamePair(int style, String tzid, Locale loc, boolean warnOnly) { |
| /* Note: There are two problems here. |
| * |
| * It looks Java 6 requires a TimeZoneNameProvider to return both standard name and daylight name |
| * for a zone. If the provider implementation only returns either of them, Java 6 also ignore |
| * the other. In ICU, there are zones which do not have daylight names, especially zones which |
| * do not use daylight time. This test case does not check a standard name if its daylight name |
| * is not available because of the Java 6 implementation problem. |
| * |
| * Another problem is that ICU always use a standard name for a zone which does not use daylight |
| * saving time even daylight name is requested. |
| */ |
| |
| String icuStdName = getIcuDisplayName(tzid, false, style, loc); |
| String icuDstName = getIcuDisplayName(tzid, true, style, loc); |
| if (icuStdName != null && icuDstName != null && !icuStdName.equals(icuDstName)) { |
| checkDisplayName(false, style, tzid, loc, icuStdName, warnOnly); |
| checkDisplayName(true, style, tzid, loc, icuDstName, warnOnly); |
| } |
| } |
| |
| private String getIcuDisplayName(String tzid, boolean daylight, int style, Locale loc) { |
| String icuName = null; |
| boolean[] isSystemID = new boolean[1]; |
| String canonicalID = com.ibm.icu.util.TimeZone.getCanonicalID(tzid, isSystemID); |
| if (isSystemID[0]) { |
| long date = System.currentTimeMillis(); |
| TimeZoneNames tznames = TimeZoneNames.getInstance(ULocale.forLocale(loc)); |
| switch (style) { |
| case TimeZone.LONG: |
| icuName = daylight ? |
| tznames.getDisplayName(canonicalID, NameType.LONG_DAYLIGHT, date) : |
| tznames.getDisplayName(canonicalID, NameType.LONG_STANDARD, date); |
| break; |
| case TimeZone.SHORT: |
| icuName = daylight ? |
| tznames.getDisplayName(canonicalID, NameType.SHORT_DAYLIGHT, date) : |
| tznames.getDisplayName(canonicalID, NameType.SHORT_STANDARD, date); |
| break; |
| } |
| } |
| return icuName; |
| } |
| |
| private void checkDisplayName(boolean daylight, int style, String tzid, Locale loc, String icuname, boolean warnOnly) { |
| String styleStr = (style == TimeZone.SHORT) ? "SHORT" : "LONG"; |
| TimeZone tz = TimeZone.getTimeZone(tzid); |
| String name = tz.getDisplayName(daylight, style, loc); |
| |
| if (TestUtil.isICUExtendedLocale(loc)) { |
| // The name should be taken from ICU |
| if (!name.equals(icuname)) { |
| if (warnOnly) { |
| logln("WARNING: TimeZone name by ICU is " + icuname + ", but got " + name |
| + " for time zone " + tz.getID() + " in locale " + loc |
| + " (daylight=" + daylight + ", style=" + styleStr + ")"); |
| |
| } else { |
| errln("FAIL: TimeZone name by ICU is " + icuname + ", but got " + name |
| + " for time zone " + tz.getID() + " in locale " + loc |
| + " (daylight=" + daylight + ", style=" + styleStr + ")"); |
| } |
| } |
| } else { |
| if (!name.equals(icuname)) { |
| logln("INFO: TimeZone name by ICU is " + icuname + ", but got " + name |
| + " for time zone " + tz.getID() + " in locale " + loc |
| + " (daylight=" + daylight + ", style=" + styleStr + ")"); |
| } |
| // Try explicit ICU locale (xx_yy_ICU) |
| Locale icuLoc = TestUtil.toICUExtendedLocale(loc); |
| name = tz.getDisplayName(daylight, style, icuLoc); |
| if (!name.equals(icuname)) { |
| if (warnOnly) { |
| logln("WARNING: TimeZone name by ICU is " + icuname + ", but got " + name |
| + " for time zone " + tz.getID() + " in locale " + icuLoc |
| + " (daylight=" + daylight + ", style=" + styleStr + ")"); |
| } else { |
| errln("FAIL: TimeZone name by ICU is " + icuname + ", but got " + name |
| + " for time zone " + tz.getID() + " in locale " + icuLoc |
| + " (daylight=" + daylight + ", style=" + styleStr + ")"); |
| } |
| } |
| } |
| } |
| |
| @Test |
| public void testGetInstance_Locale() { |
| TimeZoneNames uLocaleInstance = TimeZoneNames.getInstance(ULocale.CANADA); |
| TimeZoneNames localeInstance = TimeZoneNames.getInstance(Locale.CANADA); |
| |
| Set<String> uLocaleAvailableIds = uLocaleInstance.getAvailableMetaZoneIDs(); |
| Set<String> localeAvailableIds = localeInstance.getAvailableMetaZoneIDs(); |
| assertEquals("Available ids", uLocaleAvailableIds, localeAvailableIds); |
| |
| for (String availableId : uLocaleAvailableIds) { |
| long date = 1458385200000L; |
| TimeZoneNames.NameType nameType = TimeZoneNames.NameType.SHORT_GENERIC; |
| String uLocaleName = uLocaleInstance.getDisplayName(availableId, nameType, date); |
| String localeName = localeInstance.getDisplayName(availableId, nameType, date); |
| assertEquals("Id: " + availableId, uLocaleName, localeName); |
| } |
| } |
| |
| @Test |
| public void testGetAvailableMetaZoneIDs() { |
| TimeZoneNames japaneseNames = TimeZoneNames.getInstance(ULocale.JAPANESE); |
| Set<String> allJapan = japaneseNames.getAvailableMetaZoneIDs(); |
| |
| TimeZoneNames tzdbNames = TimeZoneNames.getTZDBInstance(ULocale.CHINESE); |
| Set<String> tzdbAll = tzdbNames.getAvailableMetaZoneIDs(); |
| |
| // The data is the same in the current implementation. |
| assertEquals("MetaZone IDs different between locales", allJapan, tzdbAll); |
| |
| // Make sure that there is something. |
| assertTrue("count of zone ids is less than 100", allJapan.size() >= 180); |
| } |
| |
| @Test |
| public void testGetAvailableMetaZoneIDs_String() { |
| TimeZoneNames japaneseNames = TimeZoneNames.getInstance(ULocale.JAPANESE); |
| assertEquals("Timezone name mismatch", Collections.singleton("America_Pacific"), |
| japaneseNames.getAvailableMetaZoneIDs("America/Los_Angeles")); |
| |
| TimeZoneNames tzdbNames = TimeZoneNames.getTZDBInstance(ULocale.CHINESE); |
| assertEquals("Timezone name mismatch", Collections.singleton("Taipei"), |
| tzdbNames.getAvailableMetaZoneIDs("Asia/Taipei")); |
| } |
| |
| @Test |
| public void testGetMetaZoneDisplayName() { |
| TimeZoneNames usNames = TimeZoneNames.getInstance(ULocale.US); |
| |
| String europeanCentralName = usNames.getMetaZoneDisplayName("Europe_Central", |
| TimeZoneNames.NameType.LONG_STANDARD); |
| assertEquals("Timezone name mismatch", "Central European Standard Time", |
| europeanCentralName); |
| |
| TimeZoneNames tzdbNames = TimeZoneNames.getTZDBInstance(ULocale.CHINESE); |
| String americaPacificName = tzdbNames.getMetaZoneDisplayName("America_Pacific", |
| TimeZoneNames.NameType.SHORT_DAYLIGHT); |
| assertEquals("Timezone name mismatch", "PDT", americaPacificName); |
| } |
| |
| @Test |
| public void testGetMetaZoneID() { |
| TimeZoneNames usNames = TimeZoneNames.getInstance(ULocale.US); |
| |
| String europeanCentralName = usNames.getMetaZoneID("Europe/Paris", 0); |
| assertEquals("Timezone name mismatch", "Europe_Central", europeanCentralName); |
| |
| TimeZoneNames tzdbNames = TimeZoneNames.getTZDBInstance(ULocale.KOREAN); |
| String seoulName = tzdbNames.getMetaZoneID("Asia/Seoul", 0); |
| assertEquals("Timezone name mismatch", "Korea", seoulName); |
| |
| // Now try Jan 1st 1945 GMT |
| seoulName = tzdbNames.getMetaZoneID("Asia/Seoul", -786240000000L); |
| assertNull("Timezone name mismatch", seoulName); |
| } |
| |
| @Test |
| public void testGetTimeZoneDisplayName() { |
| TimeZoneNames frenchNames = TimeZoneNames.getInstance(ULocale.FRENCH); |
| String dublinName = frenchNames.getTimeZoneDisplayName("Europe/Dublin", |
| TimeZoneNames.NameType.LONG_DAYLIGHT); |
| assertEquals("Timezone name mismatch", "heure d’été irlandaise", dublinName); |
| |
| String dublinLocation = frenchNames.getTimeZoneDisplayName("Europe/Dublin", |
| TimeZoneNames.NameType.EXEMPLAR_LOCATION); |
| assertEquals("Timezone name mismatch", "Dublin", dublinLocation); |
| |
| // All the names returned by this are null. |
| TimeZoneNames tzdbNames = TimeZoneNames.getTZDBInstance(ULocale.KOREAN); |
| for (String tzId : TimeZone.getAvailableIDs()) { |
| for (TimeZoneNames.NameType nameType : TimeZoneNames.NameType.values()) { |
| String name = tzdbNames.getTimeZoneDisplayName(tzId, nameType); |
| assertNull("TZ:" + tzId + ", NameType: " + nameType + ", value: " + name, name); |
| } |
| } |
| } |
| } |