diff --git a/sdk/src/main/java/io/dapr/utils/DurationUtils.java b/sdk/src/main/java/io/dapr/utils/DurationUtils.java index 9a4614b3f..01bbdb61e 100644 --- a/sdk/src/main/java/io/dapr/utils/DurationUtils.java +++ b/sdk/src/main/java/io/dapr/utils/DurationUtils.java @@ -26,32 +26,56 @@ public class DurationUtils { public static Duration convertDurationFromDaprFormat(String valueString) { // Convert the format returned by the Dapr runtime into Duration // An example of the format is: 4h15m50s60ms. It does not include days. + if (valueString == null) { + throw new IllegalArgumentException("duration string cannot be null"); + } + Duration parsedDuration = Duration.ZERO; int hourIndex = valueString.indexOf('h'); + // Get first occurrence of "m" int minuteIndex = valueString.indexOf('m'); + // Check if that is not "ms" + if (minuteIndex != -1 && valueString.length() > minuteIndex + 1 && valueString.charAt(minuteIndex + 1) == 's') { + // condition satisfied when "m" is part of the string "ms" + minuteIndex = -1; + } + // Get first occurrence of "s" int secondIndex = valueString.indexOf('s'); - int milliIndex = valueString.indexOf("ms"); + if (secondIndex != -1 && valueString.charAt(secondIndex - 1) == 'm') { + // condition satisfied when "s" is part of the string "ms" + secondIndex = -1; + } + // Declaring it final to skip checkstyle issues + final int milliIndex = valueString.indexOf("ms"); - String hoursSpan = valueString.substring(0, hourIndex); + if (hourIndex != -1) { + String hoursSpan = valueString.substring(0, hourIndex); - int hours = Integer.parseInt(hoursSpan); - int days = hours / 24; - hours = hours % 24; + int hours = Integer.parseInt(hoursSpan); + int days = hours / 24; + hours = hours % 24; + parsedDuration = parsedDuration.plusDays(days) + .plusHours(hours); + } - String minutesSpan = valueString.substring(hourIndex + 1, minuteIndex); - int minutes = Integer.parseInt(minutesSpan); + if (minuteIndex != -1) { + String minutesSpan = valueString.substring(hourIndex + 1, minuteIndex); + int minutes = Integer.parseInt(minutesSpan); + parsedDuration = parsedDuration.plusMinutes(minutes); + } - String secondsSpan = valueString.substring(minuteIndex + 1, secondIndex); - int seconds = Integer.parseInt(secondsSpan); + if (secondIndex != -1) { + String secondsSpan = valueString.substring(minuteIndex + 1, secondIndex); + int seconds = Integer.parseInt(secondsSpan); + parsedDuration = parsedDuration.plusSeconds(seconds); + } - String millisecondsSpan = valueString.substring(secondIndex + 1, milliIndex); - int milliseconds = Integer.parseInt(millisecondsSpan); + if (milliIndex != -1) { + String millisecondsSpan = valueString.substring(secondIndex + 1, milliIndex); + int milliseconds = Integer.parseInt(millisecondsSpan); + parsedDuration = parsedDuration.plusMillis(milliseconds); + } - return Duration.ZERO - .plusDays(days) - .plusHours(hours) - .plusMinutes(minutes) - .plusSeconds(seconds) - .plusMillis(milliseconds); + return parsedDuration; } /** @@ -65,8 +89,7 @@ public class DurationUtils { // return empty string for anything negative, it'll only happen for reminder "periods", not dueTimes. A // negative "period" means fire once only. - if (value == Duration.ZERO - || (value.compareTo(Duration.ZERO) == 1)) { + if (value == Duration.ZERO || (value.compareTo(Duration.ZERO) > 0)) { long hours = getDaysPart(value) * 24 + getHoursPart(value); StringBuilder sb = new StringBuilder(); diff --git a/sdk/src/test/java/io/dapr/utils/DurationUtilsTest.java b/sdk/src/test/java/io/dapr/utils/DurationUtilsTest.java index 5e7d1ac69..5c807d0f5 100644 --- a/sdk/src/test/java/io/dapr/utils/DurationUtilsTest.java +++ b/sdk/src/test/java/io/dapr/utils/DurationUtilsTest.java @@ -29,6 +29,76 @@ public class DurationUtilsTest { Assert.assertEquals(s, t); } + @Test + public void testParsePartialDurationMillis(){ + String s = "0h0m0s101ms"; + String partial = "101ms"; + Duration d1 = DurationUtils.convertDurationFromDaprFormat(partial); + + String t = DurationUtils.convertDurationToDaprFormat(d1); + Assert.assertEquals(s, t); + } + + @Test + public void testParsePartialDurationSeconds(){ + String s = "0h0m42s0ms"; + String partial = "42s"; + Duration d1 = DurationUtils.convertDurationFromDaprFormat(partial); + + String t = DurationUtils.convertDurationToDaprFormat(d1); + Assert.assertEquals(s, t); + } + + @Test + public void testParsePartialDurationMinutes(){ + String s = "0h29m0s0ms"; + String partial = "29m"; + Duration d1 = DurationUtils.convertDurationFromDaprFormat(partial); + + String t = DurationUtils.convertDurationToDaprFormat(d1); + Assert.assertEquals(s, t); + } + + @Test + public void testParsePartialDurationHours(){ + String s = "17h0m0s0ms"; + String partial = "17h"; + Duration d1 = DurationUtils.convertDurationFromDaprFormat(partial); + + String t = DurationUtils.convertDurationToDaprFormat(d1); + Assert.assertEquals(s, t); + } + + @Test + public void testZeroDurationString(){ + String s = "0h0m0s0ms"; + String partial = "0"; + Duration d1 = DurationUtils.convertDurationFromDaprFormat(partial); + + String t = DurationUtils.convertDurationToDaprFormat(d1); + Assert.assertEquals(s, t); + } + + @Test + public void testZeroDuration(){ + String s = "0h0m0s0ms"; + String t = DurationUtils.convertDurationToDaprFormat(Duration.ZERO); + Assert.assertEquals(s, t); + } + + @Test + public void testNullString() { + Assert.assertThrows(IllegalArgumentException.class, () ->{ + DurationUtils.convertDurationFromDaprFormat(null); + }); + } + + @Test + public void testEmptyString() { + Duration d = DurationUtils.convertDurationFromDaprFormat(""); + Assert.assertEquals(Duration.ZERO, d); + } + @Test public void largeHours() { // hours part is larger than 24