NIFI-3719:

- Removing the usage of SimpleDateFormat when formatting hours/minutes/seconds as the current timezone could cause unintended results.

This closes #1871.
This commit is contained in:
Matt Gilman 2017-05-31 00:45:04 +09:30 committed by Mark Payne
parent 2b435cdfc6
commit 7bcccb10f4
2 changed files with 42 additions and 12 deletions

View File

@ -17,9 +17,6 @@
package org.apache.nifi.util; package org.apache.nifi.util;
import java.text.NumberFormat; import java.text.NumberFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@ -66,8 +63,16 @@ public class FormatUtils {
*/ */
public static String formatMinutesSeconds(final long sourceDuration, final TimeUnit sourceUnit) { public static String formatMinutesSeconds(final long sourceDuration, final TimeUnit sourceUnit) {
final long millis = TimeUnit.MILLISECONDS.convert(sourceDuration, sourceUnit); final long millis = TimeUnit.MILLISECONDS.convert(sourceDuration, sourceUnit);
final SimpleDateFormat formatter = new SimpleDateFormat("mm:ss.SSS", Locale.US);
return formatter.format(new Date(millis)); final long millisInMinute = TimeUnit.MILLISECONDS.convert(1, TimeUnit.MINUTES);
final int minutes = (int) (millis / millisInMinute);
final long secondsMillisLeft = millis - minutes * millisInMinute;
final long millisInSecond = TimeUnit.MILLISECONDS.convert(1, TimeUnit.SECONDS);
final int seconds = (int) (secondsMillisLeft / millisInSecond);
final long millisLeft = secondsMillisLeft - seconds * millisInSecond;
return pad2Places(minutes) + ":" + pad2Places(seconds) + "." + pad3Places(millisLeft);
} }
/** /**
@ -79,17 +84,22 @@ public class FormatUtils {
*/ */
public static String formatHoursMinutesSeconds(final long sourceDuration, final TimeUnit sourceUnit) { public static String formatHoursMinutesSeconds(final long sourceDuration, final TimeUnit sourceUnit) {
final long millis = TimeUnit.MILLISECONDS.convert(sourceDuration, sourceUnit); final long millis = TimeUnit.MILLISECONDS.convert(sourceDuration, sourceUnit);
final long millisInHour = TimeUnit.MILLISECONDS.convert(1, TimeUnit.HOURS); final long millisInHour = TimeUnit.MILLISECONDS.convert(1, TimeUnit.HOURS);
final int hours = (int) (millis / millisInHour); final int hours = (int) (millis / millisInHour);
final long whatsLeft = millis - hours * millisInHour; final long minutesSecondsMillisLeft = millis - hours * millisInHour;
return pad(hours) + ":" + new SimpleDateFormat("mm:ss.SSS", Locale.US).format(new Date(whatsLeft)); return pad2Places(hours) + ":" + formatMinutesSeconds(minutesSecondsMillisLeft, TimeUnit.MILLISECONDS);
} }
private static String pad(final int val) { private static String pad2Places(final long val) {
return (val < 10) ? "0" + val : String.valueOf(val); return (val < 10) ? "0" + val : String.valueOf(val);
} }
private static String pad3Places(final long val) {
return (val < 100) ? "0" + pad2Places(val) : String.valueOf(val);
}
/** /**
* Formats the specified data size in human readable format. * Formats the specified data size in human readable format.
* *

View File

@ -16,13 +16,12 @@
*/ */
package org.apache.nifi.processor; package org.apache.nifi.processor;
import static org.junit.Assert.assertEquals; import org.apache.nifi.util.FormatUtils;
import org.junit.Test;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import org.apache.nifi.util.FormatUtils; import static org.junit.Assert.assertEquals;
import org.junit.Test;
public class TestFormatUtils { public class TestFormatUtils {
@ -37,4 +36,25 @@ public class TestFormatUtils {
assertEquals(60, FormatUtils.getTimeDuration("1 Hrs", TimeUnit.MINUTES)); assertEquals(60, FormatUtils.getTimeDuration("1 Hrs", TimeUnit.MINUTES));
} }
@Test
public void testFormatTime() throws Exception {
assertEquals("00:00:00.000", FormatUtils.formatHoursMinutesSeconds(0, TimeUnit.DAYS));
assertEquals("01:00:00.000", FormatUtils.formatHoursMinutesSeconds(1, TimeUnit.HOURS));
assertEquals("02:00:00.000", FormatUtils.formatHoursMinutesSeconds(2, TimeUnit.HOURS));
assertEquals("00:01:00.000", FormatUtils.formatHoursMinutesSeconds(1, TimeUnit.MINUTES));
assertEquals("00:00:10.000", FormatUtils.formatHoursMinutesSeconds(10, TimeUnit.SECONDS));
assertEquals("00:00:00.777", FormatUtils.formatHoursMinutesSeconds(777, TimeUnit.MILLISECONDS));
assertEquals("00:00:07.777", FormatUtils.formatHoursMinutesSeconds(7777, TimeUnit.MILLISECONDS));
assertEquals("20:11:36.897", FormatUtils.formatHoursMinutesSeconds(TimeUnit.MILLISECONDS.convert(20, TimeUnit.HOURS)
+ TimeUnit.MILLISECONDS.convert(11, TimeUnit.MINUTES)
+ TimeUnit.MILLISECONDS.convert(36, TimeUnit.SECONDS)
+ TimeUnit.MILLISECONDS.convert(897, TimeUnit.MILLISECONDS), TimeUnit.MILLISECONDS));
assertEquals("1000:01:01.001", FormatUtils.formatHoursMinutesSeconds(TimeUnit.MILLISECONDS.convert(999, TimeUnit.HOURS)
+ TimeUnit.MILLISECONDS.convert(60, TimeUnit.MINUTES)
+ TimeUnit.MILLISECONDS.convert(60, TimeUnit.SECONDS)
+ TimeUnit.MILLISECONDS.convert(1001, TimeUnit.MILLISECONDS), TimeUnit.MILLISECONDS));
}
} }