From cf4138d7bc1a892295ccd58ea8b42f7c8737239a Mon Sep 17 00:00:00 2001 From: Sebastian Bazley Date: Mon, 3 Mar 2014 21:10:40 +0000 Subject: [PATCH] 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 --- src/changes/changes.xml | 4 ++ .../lang3/time/DurationFormatUtils.java | 56 +++++++++---------- .../lang3/time/DurationFormatUtilsTest.java | 12 +++- 3 files changed, 42 insertions(+), 30 deletions(-) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 8768f81e8..74de399ef 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -21,6 +21,10 @@ + + DurationFormatUtils does not handle large durations correctly + + ReflectionToStringBuilder.toString does not debug 3rd party object fields within 3rd party object Add methods for removing all invalid characters according to XML 1.0 and XML 1.1 in an input string to StringEscapeUtils 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 09e636b4f..f8b9d92d2 100644 --- a/src/main/java/org/apache/commons/lang3/time/DurationFormatUtils.java +++ b/src/main/java/org/apache/commons/lang3/time/DurationFormatUtils.java @@ -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"; 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 d56ce725a..d144a0488 100644 --- a/src/test/java/org/apache/commons/lang3/time/DurationFormatUtilsTest.java +++ b/src/test/java/org/apache/commons/lang3/time/DurationFormatUtilsTest.java @@ -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);