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() {

Reply via email to