LANG-984 DurationFormatUtils does not handle large durations correctly

git-svn-id: https://svn.apache.org/repos/asf/commons/proper/lang/trunk@1573749 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Sebastian Bazley 2014-03-03 21:10:40 +00:00
parent ddc06197e4
commit cf4138d7bc
3 changed files with 42 additions and 30 deletions

View File

@ -21,6 +21,10 @@
</properties>
<body>
<release version="3.4" date="TBA" description="TBA">
<action issue="LANG-984" type="fix" dev="sebb">DurationFormatUtils does not handle large durations correctly</action>
</release>
<release version="3.3" date="TBA" description="Bug fixes and and new features including: DifferenceBuilder, ClassPathUtils, RandomUtils and Jaro-Winkler String distance metric">
<action issue="LANG-621" type="fix" dev="kinow" due-to="Philip Hodges, Thomas Neidhart">ReflectionToStringBuilder.toString does not debug 3rd party object fields within 3rd party object</action>
<action issue="LANG-955" type="add" dev="britter" due-to="Adam Hooper">Add methods for removing all invalid characters according to XML 1.0 and XML 1.1 in an input string to StringEscapeUtils</action>

View File

@ -123,30 +123,30 @@ public static String formatDuration(long durationMillis, final String format, fi
final Token[] tokens = lexx(format);
int days = 0;
int hours = 0;
int minutes = 0;
int seconds = 0;
int milliseconds = 0;
long days = 0;
long hours = 0;
long minutes = 0;
long seconds = 0;
long milliseconds = 0;
if (Token.containsTokenWithValue(tokens, d) ) {
days = (int) (durationMillis / DateUtils.MILLIS_PER_DAY);
days = durationMillis / DateUtils.MILLIS_PER_DAY;
durationMillis = durationMillis - (days * DateUtils.MILLIS_PER_DAY);
}
if (Token.containsTokenWithValue(tokens, H) ) {
hours = (int) (durationMillis / DateUtils.MILLIS_PER_HOUR);
hours = durationMillis / DateUtils.MILLIS_PER_HOUR;
durationMillis = durationMillis - (hours * DateUtils.MILLIS_PER_HOUR);
}
if (Token.containsTokenWithValue(tokens, m) ) {
minutes = (int) (durationMillis / DateUtils.MILLIS_PER_MINUTE);
minutes = durationMillis / DateUtils.MILLIS_PER_MINUTE;
durationMillis = durationMillis - (minutes * DateUtils.MILLIS_PER_MINUTE);
}
if (Token.containsTokenWithValue(tokens, s) ) {
seconds = (int) (durationMillis / DateUtils.MILLIS_PER_SECOND);
seconds = durationMillis / DateUtils.MILLIS_PER_SECOND;
durationMillis = durationMillis - (seconds * DateUtils.MILLIS_PER_SECOND);
}
if (Token.containsTokenWithValue(tokens, S) ) {
milliseconds = (int) durationMillis;
milliseconds = durationMillis;
}
return format(tokens, 0, 0, days, hours, minutes, seconds, milliseconds, padWithZeros);
@ -411,8 +411,8 @@ public static String formatPeriod(final long startMillis, final long endMillis,
* @param padWithZeros whether to pad
* @return the formatted string
*/
static String format(final Token[] tokens, final int years, final int months, final int days, final int hours, final int minutes, final int seconds,
int milliseconds, final boolean padWithZeros) {
static String format(final Token[] tokens, final long years, final long months, final long days, final long hours, final long minutes, final long seconds,
long milliseconds, final boolean padWithZeros) {
final StringBuilder buffer = new StringBuilder();
boolean lastOutputSeconds = false;
final int sz = tokens.length;
@ -424,40 +424,32 @@ static String format(final Token[] tokens, final int years, final int months, fi
buffer.append(value.toString());
} else {
if (value == y) {
buffer.append(padWithZeros ? StringUtils.leftPad(Integer.toString(years), count, '0') : Integer
.toString(years));
buffer.append(paddedValue(years, padWithZeros, count));
lastOutputSeconds = false;
} else if (value == M) {
buffer.append(padWithZeros ? StringUtils.leftPad(Integer.toString(months), count, '0') : Integer
.toString(months));
buffer.append(paddedValue(months, padWithZeros, count));
lastOutputSeconds = false;
} else if (value == d) {
buffer.append(padWithZeros ? StringUtils.leftPad(Integer.toString(days), count, '0') : Integer
.toString(days));
buffer.append(paddedValue(days, padWithZeros, count));
lastOutputSeconds = false;
} else if (value == H) {
buffer.append(padWithZeros ? StringUtils.leftPad(Integer.toString(hours), count, '0') : Integer
.toString(hours));
buffer.append(paddedValue(hours, padWithZeros, count));
lastOutputSeconds = false;
} else if (value == m) {
buffer.append(padWithZeros ? StringUtils.leftPad(Integer.toString(minutes), count, '0') : Integer
.toString(minutes));
buffer.append(paddedValue(minutes, padWithZeros, count));
lastOutputSeconds = false;
} else if (value == s) {
buffer.append(padWithZeros ? StringUtils.leftPad(Integer.toString(seconds), count, '0') : Integer
.toString(seconds));
buffer.append(paddedValue(seconds, padWithZeros, count));
lastOutputSeconds = true;
} else if (value == S) {
if (lastOutputSeconds) {
milliseconds += 1000;
final String str = padWithZeros
? StringUtils.leftPad(Integer.toString(milliseconds), count, '0')
: Integer.toString(milliseconds);
? StringUtils.leftPad(Long.toString(milliseconds), count, '0')
: Long.toString(milliseconds);
buffer.append(str.substring(1));
} else {
buffer.append(padWithZeros
? StringUtils.leftPad(Integer.toString(milliseconds), count, '0')
: Integer.toString(milliseconds));
buffer.append(paddedValue(milliseconds, padWithZeros, count));
}
lastOutputSeconds = false;
}
@ -466,6 +458,12 @@ static String format(final Token[] tokens, final int years, final int months, fi
return buffer.toString();
}
// Helper method to simplify repetive code in format method above
private static String paddedValue(final long value, final boolean padWithZeros, final int count) {
final String longString = Long.toString(value);
return padWithZeros ? StringUtils.leftPad(longString, count, '0') : longString;
}
static final Object y = "y";
static final Object M = "M";
static final Object d = "d";

View File

@ -519,7 +519,17 @@ public void testEdgeDurations() {
new int[] { 1997, 1, 28, 0, 0, 0 }, "M d");
}
@Test
public void testLANG984() { // Long durations
assertEquals("0", DurationFormatUtils.formatDuration(0, "S"));
assertEquals(Integer.toString(Integer.MAX_VALUE), DurationFormatUtils.formatDuration(Integer.MAX_VALUE, "S"));
long maxIntPlus=Integer.MAX_VALUE;
maxIntPlus++;
assertEquals(Long.toString(maxIntPlus), DurationFormatUtils.formatDuration(maxIntPlus, "S"));
assertEquals(Long.toString(Long.MAX_VALUE), DurationFormatUtils.formatDuration(Long.MAX_VALUE, "S"));
}
@Test
public void testDurationsByBruteForce() {
bruteForce(2006, 0, 1, "d", Calendar.DAY_OF_MONTH);