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 d83eabf4a Fix DurationFormatUtils.formatPeriod() calculation when
pattern omits 'M' (#1780).
d83eabf4a is described below
commit d83eabf4ac76fd401d2bf5771e3a6b8a26358857
Author: Gary Gregory <[email protected]>
AuthorDate: Wed Sep 2 22:08:18 2026 -0400
Fix DurationFormatUtils.formatPeriod() calculation when pattern omits
'M' (#1780).
- Fix inline comment.
- Sort members.
- Remove extra blank line at EOF.
---
src/changes/changes.xml | 1 +
.../lang3/time/DurationFormatUtilsTest.java | 55 +++++++++++-----------
2 files changed, 28 insertions(+), 28 deletions(-)
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 118b73abd..7e11c17fb 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -250,6 +250,7 @@ java.lang.NullPointerException: Cannot invoke
<action type="fix" dev="ggregory" due-to="alhuda, Gary
Gregory">Keep StopWatch.formatSplitTime from clamping splits to int millis
(#1777).</action>
<action type="fix" dev="ggregory" due-to="gaurav kumar
pandey, Gary Gregory">Keep StringUtils left, right, mid, and overlay off
surrogate pair boundaries (#1776).</action>
<action type="fix" dev="ggregory" due-to="Gaurav Pandey,
Gary Gregory">Align ReflectionDiffBuilder with AbstractReflection and add cycle
detection to prevent StackOverflowError on cyclic object graphs.</action>
+ <action type="fix" dev="ggregory" due-to="gaurav kumar
pandey, Gary Gregory">Fix DurationFormatUtils.formatPeriod() calculation when
pattern omits 'M' (#1780).</action>
<!-- ADD -->
<action type="add" dev="ggregory" due-to="Gary
Gregory">Add JavaVersion.JAVA_27.</action>
<action type="add" dev="ggregory" due-to="Gary
Gregory">Add SystemUtils.IS_JAVA_27.</action>
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 6f3efe5ca..969793815 100644
--- a/src/test/java/org/apache/commons/lang3/time/DurationFormatUtilsTest.java
+++ b/src/test/java/org/apache/commons/lang3/time/DurationFormatUtilsTest.java
@@ -576,12 +576,38 @@ void testFormatPeriodLongRangeBounds() {
assertFormatPeriodOneMilli((long) Integer.MIN_VALUE - 1,
Integer.MIN_VALUE);
}
+ @Test
+ void testFormatPeriodWithoutMonths() {
+ final TimeZone timeZone = TimeZone.getTimeZone("UTC");
+ final Calendar start = Calendar.getInstance(timeZone);
+ start.set(2024, Calendar.DECEMBER, 15, 0, 0, 0);
+ start.set(Calendar.MILLISECOND, 0);
+
+ final Calendar end = Calendar.getInstance(timeZone);
+ end.set(2025, Calendar.JANUARY, 15, 0, 0, 0);
+ end.set(Calendar.MILLISECOND, 0);
+
+ // 31 days elapsed across year boundary
+ assertEquals("0 years 31 days",
DurationFormatUtils.formatPeriod(start.getTimeInMillis(),
end.getTimeInMillis(), "y' years 'd' days'", false, timeZone));
+ assertEquals("0y 31d",
DurationFormatUtils.formatPeriod(start.getTimeInMillis(),
end.getTimeInMillis(), "y'y 'd'd'", false, timeZone));
+
+ // 361 days elapsed (less than 1 full year)
+ start.set(2024, Calendar.JANUARY, 15, 0, 0, 0);
+ end.set(2025, Calendar.JANUARY, 10, 0, 0, 0);
+ assertEquals("0 years 361 days",
DurationFormatUtils.formatPeriod(start.getTimeInMillis(),
end.getTimeInMillis(), "y' years 'd' days'", false, timeZone));
+
+ // Leap year to non-leap year (Feb 29, 2024 to Feb 28, 2025 = 365 days)
+ start.set(2024, Calendar.FEBRUARY, 29, 0, 0, 0);
+ end.set(2025, Calendar.FEBRUARY, 28, 0, 0, 0);
+ assertEquals("0 years 365 days",
DurationFormatUtils.formatPeriod(start.getTimeInMillis(),
end.getTimeInMillis(), "y' years 'd' days'", false, timeZone));
+ }
+
@Test
void testFormatPeriodWithoutMonthsAfterLeapDayAnniversary() {
final TimeZone timeZone = TimeZone.getTimeZone("UTC");
final Calendar start = Calendar.getInstance(timeZone);
start.clear();
- // 2020 was not a leap year
+ // 2020 was a leap year
start.set(2020, Calendar.FEBRUARY, 29);
final Calendar end = Calendar.getInstance(timeZone);
end.clear();
@@ -804,31 +830,4 @@ void testUnmatchedOptionalTokens() {
assertIllegalArgumentException(() ->
DurationFormatUtils.formatDuration(1, "[[s"));
assertIllegalArgumentException(() ->
DurationFormatUtils.formatDuration(1, "[s]]"));
}
-
- @Test
- void testFormatPeriodWithoutMonths() {
- final TimeZone timeZone = TimeZone.getTimeZone("UTC");
- final Calendar start = Calendar.getInstance(timeZone);
- start.set(2024, Calendar.DECEMBER, 15, 0, 0, 0);
- start.set(Calendar.MILLISECOND, 0);
-
- final Calendar end = Calendar.getInstance(timeZone);
- end.set(2025, Calendar.JANUARY, 15, 0, 0, 0);
- end.set(Calendar.MILLISECOND, 0);
-
- // 31 days elapsed across year boundary
- assertEquals("0 years 31 days",
DurationFormatUtils.formatPeriod(start.getTimeInMillis(),
end.getTimeInMillis(), "y' years 'd' days'", false, timeZone));
- assertEquals("0y 31d",
DurationFormatUtils.formatPeriod(start.getTimeInMillis(),
end.getTimeInMillis(), "y'y 'd'd'", false, timeZone));
-
- // 361 days elapsed (less than 1 full year)
- start.set(2024, Calendar.JANUARY, 15, 0, 0, 0);
- end.set(2025, Calendar.JANUARY, 10, 0, 0, 0);
- assertEquals("0 years 361 days",
DurationFormatUtils.formatPeriod(start.getTimeInMillis(),
end.getTimeInMillis(), "y' years 'd' days'", false, timeZone));
-
- // Leap year to non-leap year (Feb 29, 2024 to Feb 28, 2025 = 365 days)
- start.set(2024, Calendar.FEBRUARY, 29, 0, 0, 0);
- end.set(2025, Calendar.FEBRUARY, 28, 0, 0, 0);
- assertEquals("0 years 365 days",
DurationFormatUtils.formatPeriod(start.getTimeInMillis(),
end.getTimeInMillis(), "y' years 'd' days'", false, timeZone));
- }
}
-