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.