Skip to content

Commit

Permalink
Fix adding small Duration to large Instant on JS and Native
Browse files Browse the repository at this point in the history
When adding a positive Duration < 1 second to an Instant far in the
future for which the addition implementation overflows and throws an
exception, the catch blocks would only check if the seconds component of
the Duration is > 0. However since the Duration is < 1 second, the
seconds component is not > 0 and Instant.MIN is returned instead of
Instant.MAX.

This was fixed by replacing the check against the seconds component of
the Duration with a check against the whole Duration like it was already
done in the JVM implementation.

See #263
  • Loading branch information
lukellmann authored and ilya-g committed Mar 30, 2023
1 parent cbbe4b2 commit 5a73782
Show file tree
Hide file tree
Showing 3 changed files with 12 additions and 3 deletions.
9 changes: 9 additions & 0 deletions core/common/test/InstantTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -609,4 +609,13 @@ class InstantRangeTest {
(maxValidInstant + 1.nanoseconds).until(maxValidInstant, DateTimeUnit.NANOSECOND)
maxValidInstant.until(maxValidInstant + 1.nanoseconds, DateTimeUnit.NANOSECOND)
}

// https://github.com/Kotlin/kotlinx-datetime/issues/263
@Test
fun addSmallDurationsToLargeInstants() {
for (smallDuration in listOf(1.nanoseconds, 999_999.nanoseconds, 1.seconds - 1.nanoseconds)) {
assertEquals(expected = Instant.MAX, actual = Instant.MAX + smallDuration)
assertEquals(expected = Instant.MIN, actual = Instant.MIN - smallDuration)
}
}
}
2 changes: 1 addition & 1 deletion core/js/src/Instant.kt
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public actual class Instant internal constructor(internal val value: jtInstant)
Instant(plusFix(seconds.toDouble(), nanoseconds))
} catch (e: Throwable) {
if (!e.isJodaDateTimeException()) throw e
if (seconds > 0) MAX else MIN
if (duration.isPositive()) MAX else MIN
}
}

Expand Down
4 changes: 2 additions & 2 deletions core/native/src/Instant.kt
Original file line number Diff line number Diff line change
Expand Up @@ -159,9 +159,9 @@ public actual class Instant internal constructor(public actual val epochSeconds:
try {
plus(secondsToAdd, nanosecondsToAdd.toLong())
} catch (e: IllegalArgumentException) {
if (secondsToAdd > 0) MAX else MIN
if (duration.isPositive()) MAX else MIN
} catch (e: ArithmeticException) {
if (secondsToAdd > 0) MAX else MIN
if (duration.isPositive()) MAX else MIN
}
}

Expand Down

0 comments on commit 5a73782

Please sign in to comment.