Skip to content

Commit

Permalink
[stdlib] Fix a couple of issues in Duration.parse KT-72380
Browse files Browse the repository at this point in the history
- `PT000000000000000000000000000H` expected to be zero, but parsed as an infinite duration
- `PT000000000000000000000000001S` expected to be 1 second, but parsed as an infinite duration
- `PT+-2H` expected to be an incorrect value, but parsed as "-2 hours"

 Co-authored-by: Dmitry Khalanskiy <dmitry.khalanskiy@jetbrains.com>
  • Loading branch information
ilya-g authored and qodana-bot committed Oct 24, 2024
1 parent 8d0725f commit a4804ed
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 10 deletions.
19 changes: 14 additions & 5 deletions libraries/stdlib/src/kotlin/time/Duration.kt
Original file line number Diff line number Diff line change
Expand Up @@ -998,12 +998,21 @@ private fun parseOverLongIsoComponent(value: String): Long {
val length = value.length
var startIndex = 0
if (length > 0 && value[0] in "+-") startIndex++
if ((length - startIndex) > 16 && (startIndex..value.lastIndex).all { value[it] in '0'..'9' }) {
// 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
if (length - startIndex > 16) run {
var firstNonZero = startIndex
for (index in startIndex..<length) {
when (value[index]) {
'0' -> if (firstNonZero == index) firstNonZero++
!in '1'..'9' -> return@run
}
}
if (length - firstNonZero > 16) {
// 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
}
}
// TODO: replace with just toLong after min JDK becomes 8
return if (value.startsWith("+")) value.drop(1).toLong() else value.toLong()
// TODO: replace with just toLong after the minimum supported Android SDK has the same behavior as JDK 8
return if (value.startsWith("+") && length > 1 && value[1] in '0'..'9') value.drop(1).toLong() else value.toLong()
}


Expand Down
11 changes: 6 additions & 5 deletions libraries/stdlib/test/time/DurationTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -553,13 +553,13 @@ class DurationTest {
}

// zero
test(Duration.ZERO, "PT0S", "P0D", "PT0H", "PT0M", "P0DT0H", "PT0H0M", "PT0H0S")
test(Duration.ZERO, "PT0S", "P0D", "PT0H", "PT0M", "P0DT0H", "PT0H0M", "PT0H0S", "PT000000000000000000000000H")

// single unit
test(1.days, "PT24H", "P1D", "PT1440M", "PT86400S")
test(1.hours, "PT1H")
test(1.minutes, "PT1M")
test(1.seconds, "PT1S")
test(1.seconds, "PT1S", "PT000000000000000000000001S")
test(1.milliseconds, "PT0.001S")
test(1.microseconds, "PT0.000001S")
test(1.nanoseconds, "PT0.000000001S", "PT0.0000000009S")
Expand All @@ -581,11 +581,11 @@ class DurationTest {
// with sign
test(-1.days + 15.minutes, "-PT23H45M", "PT-23H-45M", "+PT-24H+15M")
test(-1.days - 15.minutes, "-PT24H15M", "PT-24H-15M", "-PT25H-45M")
test(Duration.ZERO, "PT0S", "P1DT-24H", "+PT-1H+60M", "-PT1M-60S")
test(Duration.ZERO, "PT0S", "P1DT-24H", "+PT-1H+60M", "-PT1M-60S", "PT-000000000000000000000000H")

// infinite
test(Duration.INFINITE, "PT9999999999999H", "PT+10000000000000H", "-PT-9999999999999H", "-PT-1234567890123456789012S")
test(-Duration.INFINITE, "-PT9999999999999H", "-PT10000000000000H", "PT-1234567890123456789012S")
test(Duration.INFINITE, "PT9999999999999H", "PT+10000000000000H", "-PT-9999999999999H", "-PT-1234567890123456789012S", "PT+000000000000000001234567890123456789012H")
test(-Duration.INFINITE, "-PT9999999999999H", "-PT10000000000000H", "PT-1234567890123456789012S", "PT-000000000000000001234567890123456789012H")
}

@Test
Expand All @@ -600,6 +600,7 @@ class DurationTest {
"PT1S2S", "PT1S2H",
"P9999999999999DT-9999999999999H",
"PT1.5H", "PT0.5D", "PT.5S", "PT0.25.25S",
"PT+-2H", "PT-+2H", "PT+-01234567890123456S"
)) {
assertNull(Duration.parseIsoStringOrNull(invalidValue), invalidValue)
assertFailsWith<IllegalArgumentException>(invalidValue) { Duration.parseIsoString(invalidValue) }.let { e ->
Expand Down

0 comments on commit a4804ed

Please sign in to comment.