From a001c19cfd1c655bf5cdbc3066538410ee1cea06 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Fri, 19 Jul 2024 08:26:07 -0400 Subject: [PATCH 1/3] Add testLang1641() --- .../commons/lang3/time/FastDateFormatTest.java | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/test/java/org/apache/commons/lang3/time/FastDateFormatTest.java b/src/test/java/org/apache/commons/lang3/time/FastDateFormatTest.java index aa13e28453b..3007c515ef6 100644 --- a/src/test/java/org/apache/commons/lang3/time/FastDateFormatTest.java +++ b/src/test/java/org/apache/commons/lang3/time/FastDateFormatTest.java @@ -47,6 +47,9 @@ * Unit tests {@link org.apache.commons.lang3.time.FastDateFormat}. */ public class FastDateFormatTest extends AbstractLangTest { + + private static final String ISO_8601_DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ssZZ"; + private static final int NTHREADS = 10; private static final int NROUNDS = 10000; @@ -269,6 +272,20 @@ public void testLANG_954() { FastDateFormat.getInstance(pattern); } + @Test + public void testLang1641() { + assertSame(FastDateFormat.getInstance(ISO_8601_DATE_FORMAT), FastDateFormat.getInstance(ISO_8601_DATE_FORMAT)); + // commons-lang's GMT TimeZone + assertSame(FastDateFormat.getInstance(ISO_8601_DATE_FORMAT, FastTimeZone.getGmtTimeZone()), + FastDateFormat.getInstance(ISO_8601_DATE_FORMAT, FastTimeZone.getGmtTimeZone())); + // default TimeZone + assertSame(FastDateFormat.getInstance(ISO_8601_DATE_FORMAT, TimeZone.getDefault()), + FastDateFormat.getInstance(ISO_8601_DATE_FORMAT, TimeZone.getDefault())); + // TimeZones that are identical in every way except ID + assertNotSame(FastDateFormat.getInstance(ISO_8601_DATE_FORMAT, TimeZone.getTimeZone("Australia/Broken_Hill")), + FastDateFormat.getInstance(ISO_8601_DATE_FORMAT, TimeZone.getTimeZone("Australia/Yancowinna"))); + } + @Test public void testParseSync() throws InterruptedException { final String pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS"; From abb0ca487cefc6d6df66600769655b3527a7f63e Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Fri, 19 Jul 2024 08:27:03 -0400 Subject: [PATCH 2/3] Rename some test methods --- .../lang3/time/FastDateFormatTest.java | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/test/java/org/apache/commons/lang3/time/FastDateFormatTest.java b/src/test/java/org/apache/commons/lang3/time/FastDateFormatTest.java index 3007c515ef6..698dd1ade4c 100644 --- a/src/test/java/org/apache/commons/lang3/time/FastDateFormatTest.java +++ b/src/test/java/org/apache/commons/lang3/time/FastDateFormatTest.java @@ -248,7 +248,7 @@ public void testDateDefaults() { } @Test - public void testLANG_1152() { + public void testLang1152() { final TimeZone utc = FastTimeZone.getGmtTimeZone(); final Date date = new Date(Long.MAX_VALUE); @@ -259,19 +259,10 @@ public void testLANG_1152() { assertEquals("17/08/292278994", dateAsString); } @Test - public void testLANG_1267() { + public void testLang1267() { FastDateFormat.getInstance("yyyy-MM-dd'T'HH:mm:ss.SSSXXX"); } - /** - * According to LANG-954 (https://issues.apache.org/jira/browse/LANG-954) this is broken in Android 2.1. - */ - @Test - public void testLANG_954() { - final String pattern = "yyyy-MM-dd'T'"; - FastDateFormat.getInstance(pattern); - } - @Test public void testLang1641() { assertSame(FastDateFormat.getInstance(ISO_8601_DATE_FORMAT), FastDateFormat.getInstance(ISO_8601_DATE_FORMAT)); @@ -286,6 +277,15 @@ public void testLang1641() { FastDateFormat.getInstance(ISO_8601_DATE_FORMAT, TimeZone.getTimeZone("Australia/Yancowinna"))); } + /** + * According to LANG-954 (https://issues.apache.org/jira/browse/LANG-954) this is broken in Android 2.1. + */ + @Test + public void testLang954() { + final String pattern = "yyyy-MM-dd'T'"; + FastDateFormat.getInstance(pattern); + } + @Test public void testParseSync() throws InterruptedException { final String pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS"; From 22b41cc53943c741f6a36bdfee0c6d8a5187e346 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Wed, 5 Nov 2025 18:47:56 -0500 Subject: [PATCH 3/3] [LANG-1786] FastDateFormat logs warnings on the console using FastDateFormat on Java 25 [LANG-1786] FastDateFormat logs warnings on the console using FastDateFormat on Java 25 - Use a boolean system property when on Java 25 called "FastDateParser.ignoreTimeZoneShortIDs" if present - Remove unnecessary synchronized - Extract a constant --- pom.xml | 13 +++- .../commons/lang3/time/FastDateParser.java | 36 ++++++++-- .../commons/lang3/time/FastTimeZone.java | 2 +- .../apache/commons/lang3/time/TimeZones.java | 33 +++++++++- .../commons/lang3/time/CalendarUtilsTest.java | 8 +-- .../lang3/time/DateFormatUtilsTest.java | 22 +++---- .../commons/lang3/time/DateUtilsTest.java | 16 ++--- .../lang3/time/DurationFormatUtilsTest.java | 2 +- .../lang3/time/FastDateFormatTest.java | 26 ++++---- .../lang3/time/FastDateParserTest.java | 14 ++-- .../time/FastDateParser_MoreOrLessTest.java | 2 +- .../FastDateParser_TimeZoneStrategyTest.java | 4 +- .../lang3/time/FastDatePrinterTest.java | 14 ++-- .../time/FastDatePrinterTimeZonesTest.java | 2 +- .../commons/lang3/time/FastTimeZoneTest.java | 4 +- .../time/TimeZoneStrategyShortIdTest.java | 65 +++++++++++++++++++ 16 files changed, 197 insertions(+), 66 deletions(-) create mode 100644 src/test/java/org/apache/commons/lang3/time/TimeZoneStrategyShortIdTest.java diff --git a/pom.xml b/pom.xml index ee6b49e96d0..e1f5ddc00ef 100644 --- a/pom.xml +++ b/pom.xml @@ -162,7 +162,7 @@ scm:svn:https://dist.apache.org/repos/dist/dev/commons/lang true - 0.99 + 0.98 0.96 0.96 0.92 @@ -482,6 +482,17 @@ + + + java-25-up + + [25,) + + + + 0.99 + + benchmark diff --git a/src/main/java/org/apache/commons/lang3/time/FastDateParser.java b/src/main/java/org/apache/commons/lang3/time/FastDateParser.java index 4a7083052fd..179c03b122f 100644 --- a/src/main/java/org/apache/commons/lang3/time/FastDateParser.java +++ b/src/main/java/org/apache/commons/lang3/time/FastDateParser.java @@ -23,6 +23,7 @@ import java.text.ParseException; import java.text.ParsePosition; import java.text.SimpleDateFormat; +import java.time.ZoneId; import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; @@ -46,7 +47,10 @@ import org.apache.commons.lang3.ArraySorter; import org.apache.commons.lang3.CharUtils; +import org.apache.commons.lang3.JavaVersion; import org.apache.commons.lang3.LocaleUtils; +import org.apache.commons.lang3.SystemProperties; +import org.apache.commons.lang3.SystemUtils; /** * FastDateParser is a fast and thread-safe version of {@link java.text.SimpleDateFormat}. @@ -482,6 +486,7 @@ private StrategyAndWidth literal() { * A strategy that handles a time zone field in the parsing pattern */ static class TimeZoneStrategy extends PatternStrategy { + private static final class TzInfo { final TimeZone zone; final int dstOffset; @@ -496,6 +501,9 @@ public String toString() { return "TzInfo [zone=" + zone + ", dstOffset=" + dstOffset + "]"; } } + + private static final boolean AT_LEAST_JAVA_25 = SystemUtils.isJavaVersionAtLeast(JavaVersion.JAVA_25); + private static final String RFC_822_TIME_ZONE = "[+-]\\d{4}"; private static final String GMT_OPTION = TimeZones.GMT_ID + "[+-]\\d{1,2}:\\d{2}"; @@ -505,6 +513,22 @@ public String toString() { */ private static final int ID = 0; + /** + * Tests whether to skip the given time zone, true if TimeZone.getTimeZone(). + *

+ * On Java 25 and up, skips short IDs if {@code ignoreTimeZoneShortIDs} is true. + *

+ *

+ * This method is package private only for testing. + *

+ * + * @param tzId the ID to test. + * @return Whether to skip the given time zone ID. + */ + static boolean skipTimeZone(final String tzId, final boolean ignoreTimeZoneShortIDs) { + return tzId.equalsIgnoreCase(TimeZones.GMT_ID) || AT_LEAST_JAVA_25 && ignoreTimeZoneShortIDs && ZoneId.SHORT_IDS.containsKey(tzId); + } + private final Locale locale; /** @@ -515,6 +539,9 @@ public String toString() { /** * Constructs a Strategy that parses a TimeZone + *

+ * On Java 25 and up, skips short IDs if the property {@code "FastDateParser.ignoreTimeZoneShortIDs"} is true. + *

* * @param locale The Locale */ @@ -529,13 +556,14 @@ public String toString() { // Order is undefined. // TODO Use of getZoneStrings() is discouraged per its Javadoc. final String[][] zones = DateFormatSymbols.getInstance(locale).getZoneStrings(); + final boolean ignoreTimeZoneShortIDs = SystemProperties.getBoolean(FastDateParser.class, "ignoreTimeZoneShortIDs", () -> false); for (final String[] zoneNames : zones) { // offset 0 is the time zone ID and is not localized final String tzId = zoneNames[ID]; - if (tzId.equalsIgnoreCase(TimeZones.GMT_ID)) { + if (skipTimeZone(tzId, ignoreTimeZoneShortIDs)) { continue; } - final TimeZone tz = TimeZone.getTimeZone(tzId); + final TimeZone tz = TimeZones.getTimeZone(tzId); // offset 1 is long standard name // offset 2 is short standard name final TzInfo standard = new TzInfo(tz, false); @@ -561,10 +589,10 @@ public String toString() { } // Order is undefined. for (final String tzId : ArraySorter.sort(TimeZone.getAvailableIDs())) { - if (tzId.equalsIgnoreCase(TimeZones.GMT_ID)) { + if (skipTimeZone(tzId, ignoreTimeZoneShortIDs)) { continue; } - final TimeZone tz = TimeZone.getTimeZone(tzId); + final TimeZone tz = TimeZones.getTimeZone(tzId); final String zoneName = tz.getDisplayName(locale); if (sorted.add(zoneName)) { tzNames.put(zoneName, new TzInfo(tz, tz.observesDaylightTime())); diff --git a/src/main/java/org/apache/commons/lang3/time/FastTimeZone.java b/src/main/java/org/apache/commons/lang3/time/FastTimeZone.java index f7bc16a9381..7c252fec89b 100644 --- a/src/main/java/org/apache/commons/lang3/time/FastTimeZone.java +++ b/src/main/java/org/apache/commons/lang3/time/FastTimeZone.java @@ -77,7 +77,7 @@ public static TimeZone getTimeZone(final String id) { if (tz != null) { return tz; } - return TimeZone.getTimeZone(id); + return TimeZones.getTimeZone(id); } private static int parseInt(final String group) { diff --git a/src/main/java/org/apache/commons/lang3/time/TimeZones.java b/src/main/java/org/apache/commons/lang3/time/TimeZones.java index c63e6595cfb..3057058842b 100644 --- a/src/main/java/org/apache/commons/lang3/time/TimeZones.java +++ b/src/main/java/org/apache/commons/lang3/time/TimeZones.java @@ -17,9 +17,14 @@ package org.apache.commons.lang3.time; +import java.time.ZoneId; +import java.util.Map; import java.util.TimeZone; +import java.util.concurrent.ConcurrentHashMap; +import org.apache.commons.lang3.JavaVersion; import org.apache.commons.lang3.ObjectUtils; +import org.apache.commons.lang3.SystemUtils; /** * Helps dealing with {@link java.util.TimeZone}s. @@ -28,6 +33,10 @@ */ public class TimeZones { + private static final boolean AT_LEAST_JAVA_25 = SystemUtils.isJavaVersionAtLeast(JavaVersion.JAVA_25); + + private static final Map SHORT_IDS = new ConcurrentHashMap<>(); + /** * A public version of {@link java.util.TimeZone}'s package private {@code GMT_ID} field. */ @@ -38,7 +47,28 @@ public class TimeZones { * * @since 3.13.0 */ - public static final TimeZone GMT = TimeZone.getTimeZone(GMT_ID); + public static final TimeZone GMT = TimeZones.getTimeZone(GMT_ID); + + /** + * Delegates to {@link TimeZone#getTimeZone(String)} with special behavior on Java 25. + *

+ * On Java 25, this methods delegates once to {@link TimeZone#getTimeZone(String)} for each short ID to avoid logging deprecation warning to system error. + *

+ *

+ * On Java 25, this message is of the form: + *

+ * + *
+     * WARNING: Use of the three-letter time zone ID "the-short-id" is deprecated and it will be removed in a future release
+     * 
+ * + * @param id Same as {@link TimeZone#getTimeZone(String)}. + * @return Same as {@link TimeZone#getTimeZone(String)}. + * @since 3.20.0 + */ + public static TimeZone getTimeZone(final String id) { + return AT_LEAST_JAVA_25 && ZoneId.SHORT_IDS.containsKey(id) ? SHORT_IDS.computeIfAbsent(id, TimeZone::getTimeZone) : TimeZone.getTimeZone(id); + } /** * Returns the given TimeZone if non-{@code null}, otherwise {@link TimeZone#getDefault()}. @@ -54,5 +84,4 @@ public static TimeZone toTimeZone(final TimeZone timeZone) { /** Do not instantiate. */ private TimeZones() { } - } diff --git a/src/test/java/org/apache/commons/lang3/time/CalendarUtilsTest.java b/src/test/java/org/apache/commons/lang3/time/CalendarUtilsTest.java index f5bf4fcd488..1010af6cfb1 100644 --- a/src/test/java/org/apache/commons/lang3/time/CalendarUtilsTest.java +++ b/src/test/java/org/apache/commons/lang3/time/CalendarUtilsTest.java @@ -98,7 +98,7 @@ void testGetYear() { */ @Test void testToLocalDate() { - final Calendar calendar = new GregorianCalendar(TimeZone.getTimeZone(TimeZones.GMT_ID)); + final Calendar calendar = new GregorianCalendar(TimeZones.getTimeZone(TimeZones.GMT_ID)); calendar.setTimeInMillis(-27078001200000L); assertEquals("1111-12-08T05:00:00Z", calendar.toInstant().toString()); assertEquals(LocalDate.of(1111, Month.DECEMBER, 8), new CalendarUtils(calendar).toLocalDate()); @@ -109,7 +109,7 @@ void testToLocalDate() { @ParameterizedTest @MethodSource(TimeZonesTest.TIME_ZONE_GET_AVAILABLE_IDS) void testToLocalDateTime(final String timeZoneId) { - final TimeZone timeZone = TimeZone.getTimeZone(timeZoneId); + final TimeZone timeZone = TimeZones.getTimeZone(timeZoneId); final ZoneId zoneId = timeZone.toZoneId(); final Calendar calendar = new GregorianCalendar(timeZone); calendar.setTimeInMillis(0); @@ -122,7 +122,7 @@ void testToLocalDateTime(final String timeZoneId) { @ParameterizedTest @MethodSource(TimeZonesTest.TIME_ZONE_GET_AVAILABLE_IDS) void testToOffsetDateTime(final String timeZoneId) { - final TimeZone timeZone = TimeZone.getTimeZone(timeZoneId); + final TimeZone timeZone = TimeZones.getTimeZone(timeZoneId); final ZoneId zoneId = timeZone.toZoneId(); final Calendar calendar = new GregorianCalendar(timeZone); calendar.setTimeInMillis(0); @@ -135,7 +135,7 @@ void testToOffsetDateTime(final String timeZoneId) { @ParameterizedTest @MethodSource(TimeZonesTest.TIME_ZONE_GET_AVAILABLE_IDS) void testToZonedDateTime(final String timeZoneId) { - final TimeZone timeZone = TimeZone.getTimeZone(timeZoneId); + final TimeZone timeZone = TimeZones.getTimeZone(timeZoneId); final ZoneId zoneId = timeZone.toZoneId(); final Calendar calendar = new GregorianCalendar(timeZone); calendar.setTimeInMillis(0); diff --git a/src/test/java/org/apache/commons/lang3/time/DateFormatUtilsTest.java b/src/test/java/org/apache/commons/lang3/time/DateFormatUtilsTest.java index e6e442cdeed..25cbcc7f4c7 100644 --- a/src/test/java/org/apache/commons/lang3/time/DateFormatUtilsTest.java +++ b/src/test/java/org/apache/commons/lang3/time/DateFormatUtilsTest.java @@ -141,7 +141,7 @@ void testFormatUTC() { } private void testGmtMinus3(final String expectedValue, final String pattern) { - final TimeZone timeZone = TimeZone.getTimeZone("GMT-3"); + final TimeZone timeZone = TimeZones.getTimeZone("GMT-3"); assertFormats(expectedValue, pattern, timeZone, createFebruaryTestDate(timeZone)); } @@ -153,10 +153,10 @@ void testLANG1000() throws Exception { @Test void testLANG1462() { - final TimeZone timeZone = TimeZone.getTimeZone("GMT-3"); + final TimeZone timeZone = TimeZones.getTimeZone("GMT-3"); final Calendar calendar = createJuneTestDate(timeZone); assertEquals("20030608101112", DateFormatUtils.format(calendar, "yyyyMMddHHmmss")); - calendar.setTimeZone(TimeZone.getTimeZone("JST")); + calendar.setTimeZone(TimeZones.getTimeZone("JST")); assertEquals("20030608221112", DateFormatUtils.format(calendar, "yyyyMMddHHmmss")); } @@ -179,35 +179,35 @@ void testLang530() throws ParseException { @Test void testLang916() { - final Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("Europe/Paris")); + final Calendar cal = Calendar.getInstance(TimeZones.getTimeZone("Europe/Paris")); cal.clear(); cal.set(2009, 9, 16, 8, 42, 16); // Long. { - final String value = DateFormatUtils.format(cal.getTimeInMillis(), DateFormatUtils.ISO_DATETIME_TIME_ZONE_FORMAT.getPattern(), TimeZone.getTimeZone("Europe/Paris")); + final String value = DateFormatUtils.format(cal.getTimeInMillis(), DateFormatUtils.ISO_DATETIME_TIME_ZONE_FORMAT.getPattern(), TimeZones.getTimeZone("Europe/Paris")); assertEquals("2009-10-16T08:42:16+02:00", value, "long"); } { - final String value = DateFormatUtils.format(cal.getTimeInMillis(), DateFormatUtils.ISO_DATETIME_TIME_ZONE_FORMAT.getPattern(), TimeZone.getTimeZone("Asia/Kolkata")); + final String value = DateFormatUtils.format(cal.getTimeInMillis(), DateFormatUtils.ISO_DATETIME_TIME_ZONE_FORMAT.getPattern(), TimeZones.getTimeZone("Asia/Kolkata")); assertEquals("2009-10-16T12:12:16+05:30", value, "long"); } { - final String value = DateFormatUtils.format(cal.getTimeInMillis(), DateFormatUtils.ISO_DATETIME_TIME_ZONE_FORMAT.getPattern(), TimeZone.getTimeZone("Europe/London")); + final String value = DateFormatUtils.format(cal.getTimeInMillis(), DateFormatUtils.ISO_DATETIME_TIME_ZONE_FORMAT.getPattern(), TimeZones.getTimeZone("Europe/London")); assertEquals("2009-10-16T07:42:16+01:00", value, "long"); } // Calendar. { - final String value = DateFormatUtils.format(cal, DateFormatUtils.ISO_DATETIME_TIME_ZONE_FORMAT.getPattern(), TimeZone.getTimeZone("Europe/Paris")); + final String value = DateFormatUtils.format(cal, DateFormatUtils.ISO_DATETIME_TIME_ZONE_FORMAT.getPattern(), TimeZones.getTimeZone("Europe/Paris")); assertEquals("2009-10-16T08:42:16+02:00", value, "calendar"); } { - final String value = DateFormatUtils.format(cal, DateFormatUtils.ISO_DATETIME_TIME_ZONE_FORMAT.getPattern(), TimeZone.getTimeZone("Asia/Kolkata")); + final String value = DateFormatUtils.format(cal, DateFormatUtils.ISO_DATETIME_TIME_ZONE_FORMAT.getPattern(), TimeZones.getTimeZone("Asia/Kolkata")); assertEquals("2009-10-16T12:12:16+05:30", value, "calendar"); } { - final String value = DateFormatUtils.format(cal, DateFormatUtils.ISO_DATETIME_TIME_ZONE_FORMAT.getPattern(), TimeZone.getTimeZone("Europe/London")); + final String value = DateFormatUtils.format(cal, DateFormatUtils.ISO_DATETIME_TIME_ZONE_FORMAT.getPattern(), TimeZones.getTimeZone("Europe/London")); assertEquals("2009-10-16T07:42:16+01:00", value, "calendar"); } } @@ -215,7 +215,7 @@ void testLang916() { @DefaultLocale(language = "en") @Test void testSMTP() { - TimeZone timeZone = TimeZone.getTimeZone("GMT-3"); + TimeZone timeZone = TimeZones.getTimeZone("GMT-3"); Calendar june = createJuneTestDate(timeZone); assertFormats("Sun, 08 Jun 2003 10:11:12 -0300", DateFormatUtils.SMTP_DATETIME_FORMAT.getPattern(), diff --git a/src/test/java/org/apache/commons/lang3/time/DateUtilsTest.java b/src/test/java/org/apache/commons/lang3/time/DateUtilsTest.java index 5dac357771b..d4f7b0f5d81 100644 --- a/src/test/java/org/apache/commons/lang3/time/DateUtilsTest.java +++ b/src/test/java/org/apache/commons/lang3/time/DateUtilsTest.java @@ -66,9 +66,9 @@ @WritesDefaultLocale class DateUtilsTest extends AbstractLangTest { - private static final TimeZone TIME_ZONE_NY = TimeZone.getTimeZone("America/New_York"); + private static final TimeZone TIME_ZONE_NY = TimeZones.getTimeZone("America/New_York"); private static final TimeZone TIME_ZONE_DEFAULT = TimeZone.getDefault(); - private static final TimeZone TIME_ZONE_MET = TimeZone.getTimeZone("MET"); + private static final TimeZone TIME_ZONE_MET = TimeZones.getTimeZone("MET"); private static Date BASE_DATE; /** @@ -209,7 +209,7 @@ private static Stream testToLocalDateTimeTimeZone() { Arguments.of( LocalDateTime.of(2023, 1, 1, 14, 0), Date.from(LocalDateTime.of(2023, 1, 1, 0, 0).atOffset(ZoneOffset.UTC).toInstant()), - TimeZone.getTimeZone("Pacific/Kiritimati") + TimeZones.getTimeZone("Pacific/Kiritimati") ) ); // @formatter:on @@ -763,8 +763,8 @@ void testIsSameDay_DateNullNull() { @Test void testIsSameInstant_Cal() { - final GregorianCalendar cala = new GregorianCalendar(TimeZone.getTimeZone("GMT+1")); - final GregorianCalendar calb = new GregorianCalendar(TimeZone.getTimeZone("GMT-1")); + final GregorianCalendar cala = new GregorianCalendar(TimeZones.getTimeZone("GMT+1")); + final GregorianCalendar calb = new GregorianCalendar(TimeZones.getTimeZone("GMT-1")); cala.set(2004, Calendar.JULY, 9, 13, 45, 0); cala.set(Calendar.MILLISECOND, 0); calb.set(2004, Calendar.JULY, 9, 13, 45, 0); @@ -820,8 +820,8 @@ void testIsSameInstant_DateNullNull() { @Test void testIsSameLocalTime_Cal() { - final GregorianCalendar cala = new GregorianCalendar(TimeZone.getTimeZone("GMT+1")); - final GregorianCalendar calb = new GregorianCalendar(TimeZone.getTimeZone("GMT-1")); + final GregorianCalendar cala = new GregorianCalendar(TimeZones.getTimeZone("GMT+1")); + final GregorianCalendar calb = new GregorianCalendar(TimeZones.getTimeZone("GMT-1")); cala.set(2004, Calendar.JULY, 9, 13, 45, 0); cala.set(Calendar.MILLISECOND, 0); calb.set(2004, Calendar.JULY, 9, 13, 45, 0); @@ -1577,7 +1577,7 @@ void testTruncate_Bugzilla_31395() throws Exception { @Test void testTruncateLang59() { // Set TimeZone to Mountain Time - final TimeZone denverZone = TimeZone.getTimeZone("America/Denver"); + final TimeZone denverZone = TimeZones.getTimeZone("America/Denver"); TimeZone.setDefault(denverZone); final DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS XXX"); format.setTimeZone(denverZone); diff --git a/src/test/java/org/apache/commons/lang3/time/DurationFormatUtilsTest.java b/src/test/java/org/apache/commons/lang3/time/DurationFormatUtilsTest.java index 378b0ec2d36..b19911e6a9b 100644 --- a/src/test/java/org/apache/commons/lang3/time/DurationFormatUtilsTest.java +++ b/src/test/java/org/apache/commons/lang3/time/DurationFormatUtilsTest.java @@ -481,7 +481,7 @@ void testFormatPeriodeStartGreaterEnd() { @SuppressWarnings("deprecation") @Test void testFormatPeriodISO() { - final TimeZone timeZone = TimeZone.getTimeZone("GMT-3"); + final TimeZone timeZone = TimeZones.getTimeZone("GMT-3"); final Calendar base = Calendar.getInstance(timeZone); base.set(1970, Calendar.JANUARY, 1, 0, 0, 0); base.set(Calendar.MILLISECOND, 0); diff --git a/src/test/java/org/apache/commons/lang3/time/FastDateFormatTest.java b/src/test/java/org/apache/commons/lang3/time/FastDateFormatTest.java index 864c7ff44b0..08558c4ae70 100644 --- a/src/test/java/org/apache/commons/lang3/time/FastDateFormatTest.java +++ b/src/test/java/org/apache/commons/lang3/time/FastDateFormatTest.java @@ -157,12 +157,12 @@ void test_getInstance_String() { final FastDateFormat format1 = FastDateFormat.getInstance("MM/DD/yyyy"); final FastDateFormat format2 = FastDateFormat.getInstance("MM-DD-yyyy"); final FastDateFormat format3 = FastDateFormat.getInstance("MM-DD-yyyy"); - assertNotSame(format1, format2); assertSame(format2, format3); assertEquals("MM/DD/yyyy", format1.getPattern()); assertEquals(TimeZone.getDefault(), format1.getTimeZone()); assertEquals(TimeZone.getDefault(), format2.getTimeZone()); + assertNotNull(FastDateFormat.getInstance("yyyy-MM-dd'T'HH:mm:ssZ")); } @DefaultLocale(language = "en", country = "US") @@ -183,7 +183,7 @@ void test_getInstance_String_Locale() { void test_getInstance_String_TimeZone() { final FastDateFormat format1 = FastDateFormat.getInstance("MM/DD/yyyy", - TimeZone.getTimeZone("Atlantic/Reykjavik")); + TimeZones.getTimeZone("Atlantic/Reykjavik")); final FastDateFormat format2 = FastDateFormat.getInstance("MM/DD/yyyy"); final FastDateFormat format3 = FastDateFormat.getInstance("MM/DD/yyyy", TimeZone.getDefault()); final FastDateFormat format4 = FastDateFormat.getInstance("MM/DD/yyyy", TimeZone.getDefault()); @@ -191,7 +191,7 @@ void test_getInstance_String_TimeZone() { final FastDateFormat format6 = FastDateFormat.getInstance("MM-DD-yyyy"); assertNotSame(format1, format2); - assertEquals(TimeZone.getTimeZone("Atlantic/Reykjavik"), format1.getTimeZone()); + assertEquals(TimeZones.getTimeZone("Atlantic/Reykjavik"), format1.getTimeZone()); assertEquals(TimeZone.getDefault(), format2.getTimeZone()); assertSame(format3, format4); assertNotSame(format3, format5); @@ -203,13 +203,13 @@ void test_getInstance_String_TimeZone() { @Test void test_getInstance_String_TimeZone_Locale() { final FastDateFormat format1 = FastDateFormat.getInstance("MM/DD/yyyy", - TimeZone.getTimeZone("Atlantic/Reykjavik"), Locale.GERMANY); + TimeZones.getTimeZone("Atlantic/Reykjavik"), Locale.GERMANY); final FastDateFormat format2 = FastDateFormat.getInstance("MM/DD/yyyy", Locale.GERMANY); final FastDateFormat format3 = FastDateFormat.getInstance("MM/DD/yyyy", TimeZone.getDefault(), Locale.GERMANY); assertNotSame(format1, format2); - assertEquals(TimeZone.getTimeZone("Atlantic/Reykjavik"), format1.getTimeZone()); + assertEquals(TimeZones.getTimeZone("Atlantic/Reykjavik"), format1.getTimeZone()); assertEquals(TimeZone.getDefault(), format2.getTimeZone()); assertEquals(TimeZone.getDefault(), format3.getTimeZone()); assertEquals(Locale.GERMANY, format1.getLocale()); @@ -250,8 +250,8 @@ void testDateDefaults() { assertEquals(FastDateFormat.getDateInstance(FastDateFormat.LONG, Locale.CANADA), FastDateFormat.getDateInstance(FastDateFormat.LONG, TimeZone.getDefault(), Locale.CANADA)); - assertEquals(FastDateFormat.getDateInstance(FastDateFormat.LONG, TimeZone.getTimeZone("America/New_York")), - FastDateFormat.getDateInstance(FastDateFormat.LONG, TimeZone.getTimeZone("America/New_York"), Locale.getDefault())); + assertEquals(FastDateFormat.getDateInstance(FastDateFormat.LONG, TimeZones.getTimeZone("America/New_York")), + FastDateFormat.getDateInstance(FastDateFormat.LONG, TimeZones.getTimeZone("America/New_York"), Locale.getDefault())); assertEquals(FastDateFormat.getDateInstance(FastDateFormat.LONG), FastDateFormat.getDateInstance(FastDateFormat.LONG, TimeZone.getDefault(), Locale.getDefault())); @@ -283,8 +283,8 @@ void testLang1641() { assertSame(FastDateFormat.getInstance(ISO_8601_DATE_FORMAT, TimeZone.getDefault()), FastDateFormat.getInstance(ISO_8601_DATE_FORMAT, TimeZone.getDefault())); // TimeZones that are identical in every way except ID - assertNotSame(FastDateFormat.getInstance(ISO_8601_DATE_FORMAT, TimeZone.getTimeZone("Australia/Broken_Hill")), - FastDateFormat.getInstance(ISO_8601_DATE_FORMAT, TimeZone.getTimeZone("Australia/Yancowinna"))); + assertNotSame(FastDateFormat.getInstance(ISO_8601_DATE_FORMAT, TimeZones.getTimeZone("Australia/Broken_Hill")), + FastDateFormat.getInstance(ISO_8601_DATE_FORMAT, TimeZones.getTimeZone("Australia/Yancowinna"))); } /** @@ -398,8 +398,8 @@ void testTimeDateDefaults() { assertEquals(FastDateFormat.getDateTimeInstance(FastDateFormat.LONG, FastDateFormat.MEDIUM, Locale.CANADA), FastDateFormat.getDateTimeInstance(FastDateFormat.LONG, FastDateFormat.MEDIUM, TimeZone.getDefault(), Locale.CANADA)); - assertEquals(FastDateFormat.getDateTimeInstance(FastDateFormat.LONG, FastDateFormat.MEDIUM, TimeZone.getTimeZone("America/New_York")), - FastDateFormat.getDateTimeInstance(FastDateFormat.LONG, FastDateFormat.MEDIUM, TimeZone.getTimeZone("America/New_York"), Locale.getDefault())); + assertEquals(FastDateFormat.getDateTimeInstance(FastDateFormat.LONG, FastDateFormat.MEDIUM, TimeZones.getTimeZone("America/New_York")), + FastDateFormat.getDateTimeInstance(FastDateFormat.LONG, FastDateFormat.MEDIUM, TimeZones.getTimeZone("America/New_York"), Locale.getDefault())); assertEquals(FastDateFormat.getDateTimeInstance(FastDateFormat.LONG, FastDateFormat.MEDIUM), FastDateFormat.getDateTimeInstance(FastDateFormat.LONG, FastDateFormat.MEDIUM, TimeZone.getDefault(), Locale.getDefault())); @@ -410,8 +410,8 @@ void testTimeDefaults() { assertEquals(FastDateFormat.getTimeInstance(FastDateFormat.LONG, Locale.CANADA), FastDateFormat.getTimeInstance(FastDateFormat.LONG, TimeZone.getDefault(), Locale.CANADA)); - assertEquals(FastDateFormat.getTimeInstance(FastDateFormat.LONG, TimeZone.getTimeZone("America/New_York")), - FastDateFormat.getTimeInstance(FastDateFormat.LONG, TimeZone.getTimeZone("America/New_York"), Locale.getDefault())); + assertEquals(FastDateFormat.getTimeInstance(FastDateFormat.LONG, TimeZones.getTimeZone("America/New_York")), + FastDateFormat.getTimeInstance(FastDateFormat.LONG, TimeZones.getTimeZone("America/New_York"), Locale.getDefault())); assertEquals(FastDateFormat.getTimeInstance(FastDateFormat.LONG), FastDateFormat.getTimeInstance(FastDateFormat.LONG, TimeZone.getDefault(), Locale.getDefault())); diff --git a/src/test/java/org/apache/commons/lang3/time/FastDateParserTest.java b/src/test/java/org/apache/commons/lang3/time/FastDateParserTest.java index 3369ff38287..3c6ecf0116f 100644 --- a/src/test/java/org/apache/commons/lang3/time/FastDateParserTest.java +++ b/src/test/java/org/apache/commons/lang3/time/FastDateParserTest.java @@ -103,9 +103,9 @@ private enum Expected1806 { private static final String MDY_DASH = "MM-DD-yyyy"; private static final String MDY_SLASH = "MM/DD/yyyy"; - private static final TimeZone REYKJAVIK = TimeZone.getTimeZone("Atlantic/Reykjavik"); - private static final TimeZone NEW_YORK = TimeZone.getTimeZone("America/New_York"); - private static final TimeZone INDIA = TimeZone.getTimeZone("Asia/Calcutta"); + private static final TimeZone REYKJAVIK = TimeZones.getTimeZone("Atlantic/Reykjavik"); + private static final TimeZone NEW_YORK = TimeZones.getTimeZone("America/New_York"); + private static final TimeZone INDIA = TimeZones.getTimeZone("Asia/Calcutta"); private static final Locale SWEDEN = new Locale("sv", "SE"); @@ -383,7 +383,7 @@ void testLANG_832(final TriFunction dpProv @ParameterizedTest @MethodSource(DATE_PARSER_PARAMETERS) void testLang1121(final TriFunction dpProvider) throws ParseException { - final TimeZone kst = TimeZone.getTimeZone("KST"); + final TimeZone kst = TimeZones.getTimeZone("KST"); final DateParser fdp = getInstance(dpProvider, "yyyyMMdd", kst, Locale.KOREA); assertThrows(ParseException.class, () -> fdp.parse("2015")); @@ -434,7 +434,7 @@ void testLang303() throws ParseException { void testLang538() throws ParseException { final DateParser parser = getInstance("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", TimeZones.GMT); - final Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT-8")); + final Calendar cal = Calendar.getInstance(TimeZones.getTimeZone("GMT-8")); cal.clear(); cal.set(2009, Calendar.OCTOBER, 16, 8, 42, 16); @@ -591,12 +591,12 @@ void testParseZone(final TriFunction dpPro assertEquals(cal.getTime(), fdf.parse("2003-07-10T16:33:20.000 Eastern Daylight Time")); assertEquals(cal.getTime(), fdf.parse("2003-07-10T16:33:20.000 EDT")); - cal.setTimeZone(TimeZone.getTimeZone("GMT-3")); + cal.setTimeZone(TimeZones.getTimeZone("GMT-3")); cal.set(2003, Calendar.FEBRUARY, 10, 9, 0, 0); assertEquals(cal.getTime(), fdf.parse("2003-02-10T09:00:00.000 -0300")); - cal.setTimeZone(TimeZone.getTimeZone("GMT+5")); + cal.setTimeZone(TimeZones.getTimeZone("GMT+5")); cal.set(2003, Calendar.FEBRUARY, 10, 15, 5, 6); assertEquals(cal.getTime(), fdf.parse("2003-02-10T15:05:06.000 +0500")); diff --git a/src/test/java/org/apache/commons/lang3/time/FastDateParser_MoreOrLessTest.java b/src/test/java/org/apache/commons/lang3/time/FastDateParser_MoreOrLessTest.java index 79e31aa9657..77eae646a16 100644 --- a/src/test/java/org/apache/commons/lang3/time/FastDateParser_MoreOrLessTest.java +++ b/src/test/java/org/apache/commons/lang3/time/FastDateParser_MoreOrLessTest.java @@ -31,7 +31,7 @@ class FastDateParser_MoreOrLessTest extends AbstractLangTest { - private static final TimeZone NEW_YORK = TimeZone.getTimeZone("America/New_York"); + private static final TimeZone NEW_YORK = TimeZones.getTimeZone("America/New_York"); @Test void testInputHasLessCharacters() { diff --git a/src/test/java/org/apache/commons/lang3/time/FastDateParser_TimeZoneStrategyTest.java b/src/test/java/org/apache/commons/lang3/time/FastDateParser_TimeZoneStrategyTest.java index 8a4a137acae..99c3feaebf3 100644 --- a/src/test/java/org/apache/commons/lang3/time/FastDateParser_TimeZoneStrategyTest.java +++ b/src/test/java/org/apache/commons/lang3/time/FastDateParser_TimeZoneStrategyTest.java @@ -141,7 +141,7 @@ void testTimeZoneStrategy_TimeZone(final Locale locale) { private void testTimeZoneStrategyPattern(final String languageTag, final String source) throws ParseException { final Locale locale = Locale.forLanguageTag(languageTag); - final TimeZone timeZone = TimeZone.getTimeZone("Etc/UTC"); + final TimeZone timeZone = TimeZones.getTimeZone("Etc/UTC"); assumeFalse(LocaleUtils.isLanguageUndetermined(locale), () -> toFailureMessage(locale, languageTag, timeZone)); assumeTrue(LocaleUtils.isAvailableLocale(locale), () -> toFailureMessage(locale, languageTag, timeZone)); final FastDateParser parser = new FastDateParser("z", timeZone, locale); @@ -217,7 +217,7 @@ private void testTimeZoneStrategyPattern_TimeZone_getAvailableIDs(final Locale l assumeFalse(LocaleUtils.isLanguageUndetermined(locale), () -> toFailureMessage(locale, null, null)); assumeTrue(LocaleUtils.isAvailableLocale(locale), () -> toFailureMessage(locale, null, null)); for (final String id : ArraySorter.sort(TimeZone.getAvailableIDs())) { - final TimeZone timeZone = TimeZone.getTimeZone(id); + final TimeZone timeZone = TimeZones.getTimeZone(id); final String displayName = timeZone.getDisplayName(locale); final FastDateParser parser = new FastDateParser("z", timeZone, locale); try { diff --git a/src/test/java/org/apache/commons/lang3/time/FastDatePrinterTest.java b/src/test/java/org/apache/commons/lang3/time/FastDatePrinterTest.java index cb8c9deca01..2f25f26b439 100644 --- a/src/test/java/org/apache/commons/lang3/time/FastDatePrinterTest.java +++ b/src/test/java/org/apache/commons/lang3/time/FastDatePrinterTest.java @@ -59,8 +59,8 @@ private enum Expected1806 { } private static final String YYYY_MM_DD = "yyyy/MM/dd"; - private static final TimeZone NEW_YORK = TimeZone.getTimeZone("America/New_York"); - private static final TimeZone INDIA = TimeZone.getTimeZone("Asia/Calcutta"); + private static final TimeZone NEW_YORK = TimeZones.getTimeZone("America/New_York"); + private static final TimeZone INDIA = TimeZones.getTimeZone("Asia/Calcutta"); private static final Locale SWEDEN = new Locale("sv", "SE"); @@ -259,7 +259,7 @@ void testLang303() { void testLang538() { // more commonly constructed with: cal = new GregorianCalendar(2009, 9, 16, 8, 42, 16) // for the unit test to work in any time zone, constructing with GMT-8 rather than default locale time zone - final GregorianCalendar cal = new GregorianCalendar(TimeZone.getTimeZone("GMT-8")); + final GregorianCalendar cal = new GregorianCalendar(TimeZones.getTimeZone("GMT-8")); cal.clear(); cal.set(2009, Calendar.OCTOBER, 16, 8, 42, 16); @@ -289,21 +289,21 @@ void testLang645() { @Test void testLang916() { - final Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("Europe/Paris")); + final Calendar cal = Calendar.getInstance(TimeZones.getTimeZone("Europe/Paris")); cal.clear(); cal.set(2009, 9, 16, 8, 42, 16); // calendar fast. { - final String value = FastDateFormat.getInstance("yyyy-MM-dd'T'HH:mm:ss Z", TimeZone.getTimeZone("Europe/Paris")).format(cal); + final String value = FastDateFormat.getInstance("yyyy-MM-dd'T'HH:mm:ss Z", TimeZones.getTimeZone("Europe/Paris")).format(cal); assertEquals("2009-10-16T08:42:16 +0200", value, "calendar"); } { - final String value = FastDateFormat.getInstance("yyyy-MM-dd'T'HH:mm:ss Z", TimeZone.getTimeZone("Asia/Kolkata")).format(cal); + final String value = FastDateFormat.getInstance("yyyy-MM-dd'T'HH:mm:ss Z", TimeZones.getTimeZone("Asia/Kolkata")).format(cal); assertEquals("2009-10-16T12:12:16 +0530", value, "calendar"); } { - final String value = FastDateFormat.getInstance("yyyy-MM-dd'T'HH:mm:ss Z", TimeZone.getTimeZone("Europe/London")).format(cal); + final String value = FastDateFormat.getInstance("yyyy-MM-dd'T'HH:mm:ss Z", TimeZones.getTimeZone("Europe/London")).format(cal); assertEquals("2009-10-16T07:42:16 +0100", value, "calendar"); } } diff --git a/src/test/java/org/apache/commons/lang3/time/FastDatePrinterTimeZonesTest.java b/src/test/java/org/apache/commons/lang3/time/FastDatePrinterTimeZonesTest.java index fd046d053f1..c09726e9636 100644 --- a/src/test/java/org/apache/commons/lang3/time/FastDatePrinterTimeZonesTest.java +++ b/src/test/java/org/apache/commons/lang3/time/FastDatePrinterTimeZonesTest.java @@ -32,7 +32,7 @@ class FastDatePrinterTimeZonesTest extends AbstractLangTest { private static final String PATTERN = "h:mma z"; public static Stream data() { - return Stream.of(TimeZone.getAvailableIDs()).map(TimeZone::getTimeZone); + return Stream.of(TimeZone.getAvailableIDs()).map(TimeZones::getTimeZone); } @ParameterizedTest diff --git a/src/test/java/org/apache/commons/lang3/time/FastTimeZoneTest.java b/src/test/java/org/apache/commons/lang3/time/FastTimeZoneTest.java index 08a883506b1..6135cebfaa6 100644 --- a/src/test/java/org/apache/commons/lang3/time/FastTimeZoneTest.java +++ b/src/test/java/org/apache/commons/lang3/time/FastTimeZoneTest.java @@ -18,8 +18,6 @@ import static org.junit.jupiter.api.Assertions.assertEquals; -import java.util.TimeZone; - import org.apache.commons.lang3.AbstractLangTest; import org.junit.jupiter.api.Test; @@ -71,7 +69,7 @@ void testHoursMinutes() { @Test void testOlson() { - assertEquals(TimeZone.getTimeZone("America/New_York"), FastTimeZone.getTimeZone("America/New_York")); + assertEquals(TimeZones.getTimeZone("America/New_York"), FastTimeZone.getTimeZone("America/New_York")); } @Test diff --git a/src/test/java/org/apache/commons/lang3/time/TimeZoneStrategyShortIdTest.java b/src/test/java/org/apache/commons/lang3/time/TimeZoneStrategyShortIdTest.java new file mode 100644 index 00000000000..e5f3d1fdbd4 --- /dev/null +++ b/src/test/java/org/apache/commons/lang3/time/TimeZoneStrategyShortIdTest.java @@ -0,0 +1,65 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.commons.lang3.time; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.time.ZoneId; +import java.util.Map; + +import org.apache.commons.lang3.time.FastDateParser.TimeZoneStrategy; +import org.junit.jupiter.api.condition.EnabledForJreRange; +import org.junit.jupiter.api.condition.EnabledOnJre; +import org.junit.jupiter.api.condition.JRE; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +/** + * Tests {@link TimeZoneStrategy} with and without {@link ZoneId#SHORT_IDS}. + */ +public class TimeZoneStrategyShortIdTest { + + @ParameterizedTest + @EnabledForJreRange(max = JRE.JAVA_24) + @MethodSource("org.apache.commons.lang3.time.FastDateParser_TimeZoneStrategyTest#getZoneIdStream") + void testJava24DownInvalidId(final Map.Entry entry) { + assertFalse(TimeZoneStrategy.skipTimeZone(entry.getKey(), false)); + } + + @ParameterizedTest + @EnabledForJreRange(max = JRE.JAVA_24) + @MethodSource("org.apache.commons.lang3.time.FastDateParser_TimeZoneStrategyTest#getZoneIdStream") + void testJava24DownInvalidIdCompatible(final Map.Entry entry) { + assertFalse(TimeZoneStrategy.skipTimeZone(entry.getKey(), true)); + } + + @ParameterizedTest + @EnabledOnJre(JRE.JAVA_25) + @MethodSource("org.apache.commons.lang3.time.FastDateParser_TimeZoneStrategyTest#getZoneIdStream") + void testJava25InvalidId(final Map.Entry entry) { + assertFalse(TimeZoneStrategy.skipTimeZone(entry.getKey(), false)); + } + + @ParameterizedTest + @EnabledOnJre(JRE.JAVA_25) + @MethodSource("org.apache.commons.lang3.time.FastDateParser_TimeZoneStrategyTest#getZoneIdStream") + void testJava25UpInvalidIdCompatible(final Map.Entry entry) { + assertTrue(TimeZoneStrategy.skipTimeZone(entry.getKey(), true)); + } +}