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 3f0c0fd5c Keep DurationFormatUtils.lexx() from merging repeated fields
split by a literal (#1738)
3f0c0fd5c is described below
commit 3f0c0fd5cb8af9f2ae6d7f869d7e87c66985ab90
Author: alhuda <[email protected]>
AuthorDate: Thu Jul 2 20:11:20 2026 +0530
Keep DurationFormatUtils.lexx() from merging repeated fields split by a
literal (#1738)
---
.../apache/commons/lang3/time/DurationFormatUtils.java | 4 ++++
.../commons/lang3/time/DurationFormatUtilsTest.java | 15 +++++++++++++++
2 files changed, 19 insertions(+)
diff --git
a/src/main/java/org/apache/commons/lang3/time/DurationFormatUtils.java
b/src/main/java/org/apache/commons/lang3/time/DurationFormatUtils.java
index 8f04f2b95..1b862dc6c 100644
--- a/src/main/java/org/apache/commons/lang3/time/DurationFormatUtils.java
+++ b/src/main/java/org/apache/commons/lang3/time/DurationFormatUtils.java
@@ -676,12 +676,14 @@ static Token[] lexx(final String format) {
}
optionalIndex++;
inOptional = true;
+ previous = null;
break;
case ']':
if (!inOptional) {
throw new IllegalArgumentException("Attempting to close
unopened optional block at index: " + i);
}
inOptional = false;
+ previous = null;
break;
case '\'':
if (inLiteral) {
@@ -707,6 +709,7 @@ static Token[] lexx(final String format) {
inLiteral = true;
}
}
+ previous = null;
break;
case 'y':
value = y;
@@ -735,6 +738,7 @@ static Token[] lexx(final String format) {
list.add(new Token(buffer, inOptional, optionalIndex));
}
buffer.append(ch);
+ previous = null;
}
if (value != null) {
if (previous != null && previous.getValue().equals(value)) {
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 a7155f4f8..11d81c35e 100644
--- a/src/test/java/org/apache/commons/lang3/time/DurationFormatUtilsTest.java
+++ b/src/test/java/org/apache/commons/lang3/time/DurationFormatUtilsTest.java
@@ -123,6 +123,21 @@ void testAlternatingLiteralOptionals() {
DurationFormatUtils.formatDuration(Duration.ofDays(1).plusHours(1).plusMinutes(1).plusSeconds(1).plusMillis(1).toMillis(),
format));
}
+ @Test
+ void testRepeatedTokenSeparatedByLiteral() {
+ final long fiveHours = Duration.ofHours(5).toMillis();
+ // the same field letter on either side of a literal are two separate
fields, not one padded field
+ assertEquals("5x5", DurationFormatUtils.formatDuration(fiveHours,
"HxH", false));
+ assertEquals("5x5", DurationFormatUtils.formatDuration(fiveHours,
"H'x'H", false));
+ // each H is a single-width field, so padding does not turn either
into "05"
+ assertEquals("5x5", DurationFormatUtils.formatDuration(fiveHours,
"HxH", true));
+ // separated by an optional block
+ assertEquals("5x5", DurationFormatUtils.formatDuration(fiveHours,
"H[x]H", false));
+ assertEquals("2-2",
DurationFormatUtils.formatDuration(Duration.ofDays(2).toMillis(), "d-d",
false));
+ // adjacent repeats still collapse into a single padded field
+ assertEquals("05", DurationFormatUtils.formatDuration(fiveHours, "HH",
true));
+ }
+
/** See https://issues.apache.org/bugzilla/show_bug.cgi?id=38401 */
@Test
void testBugzilla38401() {