From 5072653957bf81c496d7b1959cd42811d0b983bb Mon Sep 17 00:00:00 2001 From: Ilya Gorbunov Date: Thu, 8 Jul 2021 10:00:59 +0300 Subject: [PATCH] Duration: parse explicit positive values parenthesized --- libraries/stdlib/src/kotlin/time/Duration.kt | 10 ++++++---- libraries/stdlib/test/time/DurationTest.kt | 17 +++++++++++------ 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/libraries/stdlib/src/kotlin/time/Duration.kt b/libraries/stdlib/src/kotlin/time/Duration.kt index f35d9bcb0e0..f1ec58ce290 100644 --- a/libraries/stdlib/src/kotlin/time/Duration.kt +++ b/libraries/stdlib/src/kotlin/time/Duration.kt @@ -1074,7 +1074,8 @@ private fun parseDuration(value: String, strictIso: Boolean): Duration { when (value[index]) { '+', '-' -> index++ } - val isNegative = value.startsWith('-') + val hasSign = index > 0 + val isNegative = hasSign && value.startsWith('-') when { length <= index -> throw IllegalArgumentException("No components") @@ -1116,8 +1117,8 @@ private fun parseDuration(value: String, strictIso: Boolean): Duration { // parse default string format var prevUnit: DurationUnit? = null var afterFirst = false - var allowSpaces = !isNegative - if (isNegative && value[index] == '(' && value.last() == ')') { + var allowSpaces = !hasSign + if (hasSign && value[index] == '(' && value.last() == ')') { allowSpaces = true if (++index == --length) throw IllegalArgumentException("No components") } @@ -1158,7 +1159,8 @@ private fun parseOverLongIsoComponent(value: String): Long { // all chars are digits, but more than ceiling(log10(MAX_MILLIS / 1000)) of them return if (value[0] == '-') Long.MIN_VALUE else Long.MAX_VALUE } - return value.toLong() + // TODO: replace with just toLong after min JDK becomes 8 + return if (value.startsWith("+")) value.drop(1).toLong() else value.toLong() } diff --git a/libraries/stdlib/test/time/DurationTest.kt b/libraries/stdlib/test/time/DurationTest.kt index 8d7aa273c02..bc6d4a49ade 100644 --- a/libraries/stdlib/test/time/DurationTest.kt +++ b/libraries/stdlib/test/time/DurationTest.kt @@ -492,13 +492,13 @@ class DurationTest { test(Duration.minutes(2) + Duration.milliseconds(500), "PT2M0.500S") test(Duration.milliseconds(90_500), "PT1M30.500S") - // negative - test(-Duration.days(1) + Duration.minutes(15), "-PT23H45M", "PT-23H-45M", "PT-24H15M") + // with sign + test(-Duration.days(1) + Duration.minutes(15), "-PT23H45M", "PT-23H-45M", "+PT-24H+15M") test(-Duration.days(1) - Duration.minutes(15), "-PT24H15M", "PT-24H-15M", "-PT25H-45M") - test(Duration.ZERO, "PT0S", "P1DT-24H", "PT-1H60M", "-PT1M-60S") + test(Duration.ZERO, "PT0S", "P1DT-24H", "+PT-1H+60M", "-PT1M-60S") // infinite - test(Duration.INFINITE, "PT9999999999999H", "PT10000000000000H", "-PT-9999999999999H", "-PT-1234567890123456789012S") + test(Duration.INFINITE, "PT9999999999999H", "PT+10000000000000H", "-PT-9999999999999H", "-PT-1234567890123456789012S") test(-Duration.INFINITE, "-PT9999999999999H", "-PT10000000000000H", "PT-1234567890123456789012S") } @@ -600,9 +600,12 @@ class DurationTest { for (string in expected) { testParsing(string, duration) if (duration.isPositive() && duration.isFinite()) { + testParsing("+($string)", duration) testParsing("-($string)", -duration) - if (' ' !in string) + if (' ' !in string) { + testParsing("+$string", duration) testParsing("-$string", -duration) + } } } } @@ -682,7 +685,9 @@ class DurationTest { "1234567890123456789012ns", "Inf", "-Infinity value", "1s ", " 1s", "1d 1m 1h", "1s 2s", - "-12m 15s", "-12m -15s", "(12m 30s)", "-()", "()", "-(12m 30s", + "-12m 15s", "-12m -15s", "-()", "-(12m 30s", + "+12m 15s", "+12m +15s", "+()", "+(12m 30s", + "()", "(12m 30s)", "12.5m 11.5s", ".2s", "0.1553.39m", "P+12+34D", "P12-34D", "PT1234567890-1234567890S", " P1D", "PT1S ",