diff --git a/src/main/java/com/force/i18n/BaseLocalizer.java b/src/main/java/com/force/i18n/BaseLocalizer.java index 417470b..1e1040c 100644 --- a/src/main/java/com/force/i18n/BaseLocalizer.java +++ b/src/main/java/com/force/i18n/BaseLocalizer.java @@ -52,6 +52,7 @@ public enum LocalOrGmt { private static Function LocaleFixerFunction; // controlls leniency of parsing date. using non-lenient mode for not allowing ambiguous date such as "2/30" + // set true to avoid ICU-21301 that fails to parse the transition date for time zones with daylight saving time private static final boolean USE_LENIENT_MODE = false; static { @@ -822,22 +823,6 @@ public DateFormat getInputLongDateFormat() { return this.inputLocalLongDateFormat; } - - /** - * Copy over the settings from ICU {@code SimpleDateFormat}. - *

- * ICU-21301 fails to parse the transition date for time zones with daylight saving time. - - * see: https://unicode-org.atlassian.net/browse/ICU-21301 - */ - private static DateFormat setJdkDateFormatFromIcu(SimpleDateFormat fmtJdk, SimpleDateFormatICU fmtIcu) { - fmtJdk.applyPattern(fmtIcu.toPattern()); - fmtJdk.setNumberFormat(fmtIcu.getNumberFormat()); - fmtJdk.setDateFormatSymbols(fmtIcu.getDateFormatSymbols()); - fmtJdk.set2DigitYearStart(fmtIcu.get2DigitYearStart()); - return fmtJdk; - } - /** * Static method to get date-only DateFormat for input. This is based on a 2 digit year * input mask, which also handles 4-digit year, but caller must use doParseDate() to @@ -850,13 +835,6 @@ private static DateFormat setJdkDateFormatFromIcu(SimpleDateFormat fmtJdk, Simpl */ public static DateFormat getLocaleInputDateFormat(Locale locale, TimeZone tz) { DateFormat df = getFormatProvider(locale).getDateInstance(DateFormat.SHORT, locale); - // ICU-21301 hack: Apply only with an ICU object and when timezone has DST - if (!USE_LENIENT_MODE && df instanceof SimpleDateFormatICU && tz.useDaylightTime()) { - // (re-)construct JDK's DateFormat object and copy formatting information from ICU - DateFormat dfJdk = getJDKFormatFixer().getDateInstance(DateFormat.SHORT, locale); - df = setJdkDateFormatFromIcu((SimpleDateFormat)dfJdk, (SimpleDateFormatICU)df); - } - df.setLenient(USE_LENIENT_MODE); df.setTimeZone(tz); set2DigitYearStart(df, tz); @@ -885,13 +863,6 @@ public static DateFormat getLocaleInputDateFormat(Locale locale, int style, Time dateStyle = DateFormat.SHORT; } DateFormat df = getFormatProvider(locale).getDateInstance(dateStyle, locale); - // ICU-21301 hack: Apply only with an ICU object and when timezone has DST - if (!USE_LENIENT_MODE && df instanceof SimpleDateFormatICU && tz.useDaylightTime()) { - // (re-)construct JDK's DateFormat object and copy formatting information from ICU - DateFormat dfJdk = getJDKFormatFixer().getDateInstance(dateStyle, locale); - df = setJdkDateFormatFromIcu((SimpleDateFormat)dfJdk, (SimpleDateFormatICU)df); - } - df.setLenient(USE_LENIENT_MODE); df.setTimeZone(tz); set2DigitYearStart(df, tz); @@ -986,13 +957,6 @@ public DateFormat getInputLongDateTimeFormat() { */ public static DateFormat getLocaleInputDateTimeFormat(Locale locale, TimeZone tz) { DateFormat df = getFormatProvider(locale).getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, locale); - // ICU-21301 hack: Apply only with an ICU object and when timezone has DST - if (!USE_LENIENT_MODE && df instanceof SimpleDateFormatICU && tz.useDaylightTime()) { - // (re-)construct JDK's DateFormat object and copy formatting information from ICU - DateFormat dfJdk = getJDKFormatFixer().getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, locale); - df = setJdkDateFormatFromIcu((SimpleDateFormat)dfJdk, (SimpleDateFormatICU)df); - } - df.setLenient(USE_LENIENT_MODE); df.setTimeZone(tz); set2DigitYearStart(df, tz); @@ -1027,12 +991,6 @@ public static DateFormat getLocaleInputDateTimeFormat(Locale locale, int style, dateStyle = timeStyle = DateFormat.SHORT; } DateFormat df = getFormatProvider(locale).getDateTimeInstance(dateStyle, timeStyle, locale); - // ICU-21301 hack: Apply only with an ICU object and when timezone has DST - if (!USE_LENIENT_MODE && df instanceof SimpleDateFormatICU && tz.useDaylightTime()) { - // (re-)construct JDK's DateFormat object and copy formatting information from ICU - DateFormat dfJdk = getJDKFormatFixer().getDateTimeInstance(dateStyle, timeStyle, locale); - df = setJdkDateFormatFromIcu((SimpleDateFormat)dfJdk, (SimpleDateFormatICU)df); - } df.setLenient(USE_LENIENT_MODE); df.setTimeZone(tz); set2DigitYearStart(df, tz); @@ -1101,13 +1059,6 @@ public static DateFormat getLocaleInputTimeFormat(Locale locale, int style, Time dateStyle = DateFormat.SHORT; } DateFormat df = getFormatProvider(locale).getTimeInstance(dateStyle, locale); - // ICU-21301 hack: Apply only with an ICU object and when timezone has DST - if (!USE_LENIENT_MODE && df instanceof SimpleDateFormatICU && tz.useDaylightTime()) { - // (re-)construct JDK's DateFormat object and copy formatting information from ICU - DateFormat dfJdk = getJDKFormatFixer().getTimeInstance(dateStyle, locale); - df = setJdkDateFormatFromIcu((SimpleDateFormat)dfJdk, (SimpleDateFormatICU)df); - } - df.setLenient(USE_LENIENT_MODE); df.setTimeZone(tz); set2DigitYearStart(df, tz); diff --git a/src/test/java/com/force/i18n/BaseLocalizerTest.java b/src/test/java/com/force/i18n/BaseLocalizerTest.java index a8d65d7..0a1cc7a 100644 --- a/src/test/java/com/force/i18n/BaseLocalizerTest.java +++ b/src/test/java/com/force/i18n/BaseLocalizerTest.java @@ -8,9 +8,9 @@ package com.force.i18n; import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertThrows; import java.text.*; -import java.time.LocalDate; import java.util.*; import java.util.function.Function; import java.util.stream.Collectors; @@ -522,11 +522,9 @@ public void test4DigitYears() { /* * ICU-21301 failed to parse the transition date (e.g. 6/9/2020 for "America/Santiago") * https://unicode-org.atlassian.net/browse/ICU-21301 - * - * BaseLocalizer returns JDK's DateFormat object instead of ICU for particular time zone */ @Test - public void testParseDateOnDST() throws Exception { + public void testParseDateOnDST() { final Locale locale = Locale.GERMANY; final HumanLanguage language = HumanLanguage.Helper.get(Locale.US); @@ -536,19 +534,10 @@ public void testParseDateOnDST() throws Exception { Calendar cal = Calendar.getInstance(); cal.clear(); - BaseLocalizer icuLocalizer = new BaseLocalizer(locale, locale, TimeZone.getTimeZone("America/Santiago"), language, lSet); - assertFalse(icuLocalizer.getInputDateFormat() instanceof SimpleDateFormatICU); - Date date = icuLocalizer.parseDate("06.09.2020", DateFormat.SHORT); - cal.setTimeZone(TimeZone.getTimeZone("America/Santiago")); - cal.set(2020, 8, 6); - assertEquals(cal.getTime(), date); - - icuLocalizer = new BaseLocalizer(locale, locale, TimeZone.getTimeZone("Africa/Cairo"), language, lSet); - assertFalse(icuLocalizer.getInputDateFormat() instanceof SimpleDateFormatICU); - date = icuLocalizer.parseDate("26.4.2024", DateFormat.SHORT); - cal.setTimeZone(TimeZone.getTimeZone("Africa/Cairo")); - cal.set(2024, 3, 26); - assertEquals(cal.getTime().getTime(), date.getTime()); + final BaseLocalizer icuLocalizer = new BaseLocalizer(locale, locale, TimeZone.getTimeZone("America/Santiago"), + language, lSet); + assertTrue(icuLocalizer.getInputDateFormat() instanceof SimpleDateFormatICU); + assertThrows(ParseException.class, () -> icuLocalizer.parseDate("06.09.2020", DateFormat.SHORT)); } private static class TestSimpleIniFile extends SimpleNonConfigIniFile implements SharedLabelSet {