This is an automated email from the ASF dual-hosted git repository.

garydgregory pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-lang.git


The following commit(s) were added to refs/heads/master by this push:
     new de0184561 Return null for out-of-range offset in 
FastTimeZone.getGmtTimeZone (#1788)
de0184561 is described below

commit de0184561dd0c8c7a176470016b9df89414f8bed
Author: alhuda <[email protected]>
AuthorDate: Sat Sep 12 19:50:04 2026 +0530

    Return null for out-of-range offset in FastTimeZone.getGmtTimeZone (#1788)
---
 .../org/apache/commons/lang3/time/FastTimeZone.java  | 11 ++++++++---
 .../apache/commons/lang3/time/FastTimeZoneTest.java  | 20 ++++++++++++++++++++
 2 files changed, 28 insertions(+), 3 deletions(-)

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 e430f61c4..b25a1aeba 100644
--- a/src/main/java/org/apache/commons/lang3/time/FastTimeZone.java
+++ b/src/main/java/org/apache/commons/lang3/time/FastTimeZone.java
@@ -48,13 +48,13 @@ public static TimeZone getGmtTimeZone() {
      * <p>
      * Note: the underlying regex is lenient — every capture group (sign, 
hours, minutes, and the {@code GMT} prefix) is optional. Inputs that lack any 
digit
      * group, such as the empty string, {@code "+"}, {@code "-"}, or {@code 
"GMT"} alone, still match and the method returns the GMT TimeZone with a raw 
offset
-     * of zero (mirroring {@link TimeZone#getTimeZone(String)} JDK-parity for 
unrecognized ids). Only inputs that fail the regex outright return
-     * {@code null}.
+     * of zero (mirroring {@link TimeZone#getTimeZone(String)} JDK-parity for 
unrecognized ids). Inputs that fail the regex outright, or that match but 
specify
+     * an out-of-range offset (24 hours or 60 minutes and above), return 
{@code null}.
      * </p>
      *
      * @param pattern The GMT offset.
      * @return A TimeZone matching the (possibly partial or empty) GMT offset 
pattern, defaulting to GMT for an unrecognized but parseable input, or
-     *         {@code null} if the pattern fails the regex.
+     *         {@code null} if the pattern fails the regex or specifies an 
out-of-range offset.
      */
     public static TimeZone getGmtTimeZone(final String pattern) {
         if ("Z".equals(pattern) || "UTC".equals(pattern)) {
@@ -67,6 +67,11 @@ public static TimeZone getGmtTimeZone(final String pattern) {
             if (hours == 0 && minutes == 0) {
                 return GREENWICH;
             }
+            if (hours >= 24 || minutes >= 60) {
+                // A matching but out-of-range offset is not a valid GMT id; 
report it the documented
+                // way instead of letting the GmtTimeZone constructor throw 
IllegalArgumentException.
+                return null;
+            }
             return new GmtTimeZone(parseSign(m.group(1)), hours, minutes);
         }
         return null;
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 185d1f3f2..960c8ebcd 100644
--- a/src/test/java/org/apache/commons/lang3/time/FastTimeZoneTest.java
+++ b/src/test/java/org/apache/commons/lang3/time/FastTimeZoneTest.java
@@ -117,6 +117,26 @@ void testOlson() {
         assertEquals(TimeZones.getTimeZone("America/New_York"), 
FastTimeZone.getTimeZone("America/New_York"));
     }
 
+    @Test
+    void testOutOfRangeOffsetReturnsNull() {
+        // A pattern that matches the regex but whose hours or minutes are out 
of range is not a valid GMT id.
+        // Before the fix these threw IllegalArgumentException from the 
GmtTimeZone constructor.
+        assertNull(FastTimeZone.getGmtTimeZone("GMT+24"));
+        assertNull(FastTimeZone.getGmtTimeZone("+24"));
+        assertNull(FastTimeZone.getGmtTimeZone("-24"));
+        assertNull(FastTimeZone.getGmtTimeZone("+99"));
+        assertNull(FastTimeZone.getGmtTimeZone("+12:60"));
+        assertNull(FastTimeZone.getGmtTimeZone("00:99"));
+    }
+
+    @Test
+    void testOutOfRangeOffsetViaGetTimeZoneFallsBack() {
+        // getTimeZone must not propagate the constructor exception; a null 
GMT result falls back to the JDK lookup.
+        final TimeZone tz = FastTimeZone.getTimeZone("GMT+24");
+        assertNotNull(tz);
+        assertEquals(0, tz.getRawOffset());
+    }
+
     @Test
     void testPlusOnlyReturnsNonNull() {
         // Sign-only input still matches the regex; hours and minutes default 
to 0.

Reply via email to