commonTest.io.islandtime.measures.DurationTest.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of core-metadata Show documentation
Show all versions of core-metadata Show documentation
A multiplatform library for working with dates and times
The newest version!
package io.islandtime.measures
import io.islandtime.measures.TimeUnit.*
import io.islandtime.parser.DateTimeParseException
import kotlin.test.*
import kotlin.time.ExperimentalTime
import kotlin.time.nanoseconds as kotlinNanoseconds
import kotlin.time.seconds as kotlinSeconds
class DurationTest {
@Test
fun `ZERO returns a duration with a length of zero`() {
val duration = Duration.ZERO
assertEquals(0L.seconds, duration.seconds)
assertEquals(0.nanoseconds, duration.nanosecondAdjustment)
}
@Test
fun `durationOf() creates durations with positive hours`() {
val duration = durationOf(1.hours)
assertEquals(3600L.seconds, duration.seconds)
assertEquals(0.nanoseconds, duration.nanosecondAdjustment)
}
@Test
fun `durationOf() creates durations with negative hours`() {
val duration = durationOf((-1).hours)
assertEquals((-3600L).seconds, duration.seconds)
assertEquals(0.nanoseconds, duration.nanosecondAdjustment)
}
@Test
fun `durationOf() creates durations with positive nanoseconds`() {
val duration1 = durationOf(5.nanoseconds)
assertEquals(0L.seconds, duration1.seconds)
assertEquals(5.nanoseconds, duration1.nanosecondAdjustment)
val duration2 = durationOf(1_500_000_000.nanoseconds)
assertEquals(1L.seconds, duration2.seconds)
assertEquals(500_000_000.nanoseconds, duration2.nanosecondAdjustment)
}
@Test
fun `durationOf() creates durations with negative nanoseconds`() {
val duration1 = durationOf((-5).nanoseconds)
assertEquals(0L.seconds, duration1.seconds)
assertEquals((-5).nanoseconds, duration1.nanosecondAdjustment)
val duration2 = durationOf((-1_500_000_000).nanoseconds)
assertEquals((-1L).seconds, duration2.seconds)
assertEquals((-500_000_000).nanoseconds, duration2.nanosecondAdjustment)
}
@Test
fun `durationOf() creates durations from seconds and nanoseconds components`() {
val duration1 = durationOf(1.seconds, (-5).nanoseconds)
assertEquals(0L.seconds, duration1.seconds)
assertEquals(999_999_995.nanoseconds, duration1.nanosecondAdjustment)
val duration2 = durationOf((-2).seconds, 1_200_000_000.nanoseconds)
assertEquals(0L.seconds, duration2.seconds)
assertEquals((-800_000_000).nanoseconds, duration2.nanosecondAdjustment)
val duration3 = durationOf((-1).seconds, 1_500_000_000.nanoseconds)
assertEquals(0L.seconds, duration3.seconds)
assertEquals(500_000_000.nanoseconds, duration3.nanosecondAdjustment)
}
@Test
fun `isZero() returns true for duration of no length`() {
assertTrue { Duration.ZERO.isZero() }
}
@Test
fun `isZero() returns false for non-zero durations`() {
assertFalse { durationOf(1.seconds).isZero() }
assertFalse { durationOf((-1).seconds).isZero() }
assertFalse { durationOf(1.nanoseconds).isZero() }
}
@Test
fun `isNegative() returns true if seconds is negative`() {
assertTrue { durationOf((-1).seconds).isNegative() }
}
@Test
fun `isNegative() returns true if nanosecondAdjustment is negative`() {
assertTrue { durationOf((-1).nanoseconds).isNegative() }
}
@Test
fun `isNegative() returns false if greater or equal to zero`() {
assertFalse { Duration.ZERO.isNegative() }
assertFalse { 1.seconds.asDuration().isNegative() }
assertFalse { 1.nanoseconds.asDuration().isNegative() }
}
@Test
fun `inDays property returns the number of whole days`() {
assertEquals(1L.days, durationOf(1.days).inDays)
assertEquals((-1L).days, durationOf((-1).days).inDays)
assertEquals(0L.days, durationOf(1.days - 1.nanoseconds).inDays)
}
@Test
fun `inHours property returns the number of whole hours`() {
assertEquals(1L.hours, durationOf(1.hours).inHours)
assertEquals((-1L).hours, durationOf((-1).hours).inHours)
assertEquals(0L.hours, durationOf(1.hours - 1.nanoseconds).inHours)
}
@Test
fun `inMinutes property returns the number of whole minutes`() {
assertEquals(1L.minutes, durationOf(1.minutes).inMinutes)
assertEquals((-1L).minutes, durationOf((-1).minutes).inMinutes)
assertEquals(0L.minutes, durationOf(1.minutes - 1.nanoseconds).inMinutes)
}
@Test
fun `inMilliseconds property returns the number of whole milliseconds`() {
assertEquals(1L.milliseconds, durationOf(1.milliseconds).inMilliseconds)
assertEquals((-1L).milliseconds, durationOf((-1).milliseconds).inMilliseconds)
assertEquals(1L.milliseconds, durationOf(1.milliseconds + 1.nanoseconds).inMilliseconds)
assertEquals(0L.milliseconds, durationOf(1.milliseconds - 1.nanoseconds).inMilliseconds)
}
@Test
fun `inMilliseconds property throws an exception on overflow`() {
assertFailsWith { durationOf(Long.MAX_VALUE.seconds).inMilliseconds }
}
@Test
fun `inMicroseconds property returns the number of whole microseconds`() {
assertEquals(1L.microseconds, durationOf(1.microseconds).inMicroseconds)
assertEquals((-1L).microseconds, durationOf((-1).microseconds).inMicroseconds)
assertEquals(1L.microseconds, durationOf(1.microseconds + 1.nanoseconds).inMicroseconds)
assertEquals(0L.microseconds, durationOf(1.microseconds - 1.nanoseconds).inMicroseconds)
}
@Test
fun `inMicroseconds property throws an exception on overflow`() {
assertFailsWith { durationOf(365.days * 300_000).inMicroseconds }
}
@Test
fun `inNanoseconds property returns the number of whole nanoseconds`() {
assertEquals(1L.nanoseconds, durationOf(1.nanoseconds).inNanoseconds)
assertEquals((-1L).nanoseconds, durationOf((-1).nanoseconds).inNanoseconds)
assertEquals(1_000_000_001L.nanoseconds, durationOf(1.seconds, 1.nanoseconds).inNanoseconds)
assertEquals(0L.nanoseconds, Duration.ZERO.inNanoseconds)
}
@Test
fun `inNanoseconds property throws an exception on overflow`() {
assertFailsWith { durationOf(365.days * 300).inNanoseconds }
}
@Test
fun `unary minus negates both the seconds and nanoOfSecond`() {
assertEquals(
durationOf((-1).seconds - 1.nanoseconds),
-durationOf(1.seconds + 1.nanoseconds)
)
assertEquals(
durationOf(1.seconds + 1.nanoseconds),
-durationOf((-1).seconds - 1.nanoseconds)
)
}
@Test
fun `unary minus throws an exception on overflow`() {
assertFailsWith { -durationOf(Long.MIN_VALUE.seconds) }
}
@Test
fun `adding zero to a duration has no effect`() {
assertEquals(durationOf(1.hours), durationOf(1.hours) + Duration.ZERO)
}
@Test
fun `adding a duration to zero returns that duration`() {
assertEquals(durationOf(1.hours), Duration.ZERO + durationOf(1.hours))
}
@Test
fun `adding a positive duration to a non-zero duration sums them`() {
assertEquals(
durationOf(270L.seconds, 50.nanoseconds),
(4.minutes + 30.seconds).asDuration() + 50.nanoseconds.asDuration()
)
assertEquals(
durationOf(30.seconds),
((-1).minutes - 30.seconds).asDuration() + 2.minutes.asDuration()
)
assertEquals(
durationOf(0.seconds, (-800_000_000).nanoseconds),
durationOf((-1).seconds, (-600_000_000).nanoseconds) + durationOf(800_000_000.nanoseconds)
)
assertEquals(
durationOf(1.seconds, 999_999_998.nanoseconds),
durationOf(999_999_999.nanoseconds) + durationOf(999_999_999.nanoseconds)
)
assertEquals(
durationOf((-2).seconds),
durationOf((-2).seconds, (-500_000_000).nanoseconds) + durationOf(500_000_000.nanoseconds)
)
}
@Test
fun `subtraction of positive duration`() {
assertEquals(durationOf((-1).nanoseconds), Duration.ZERO - durationOf(1.nanoseconds))
assertEquals(durationOf(Long.MIN_VALUE.seconds), durationOf((-1).seconds) - Long.MAX_VALUE.seconds)
}
@Test
fun `subtraction of negative duration`() {
assertEquals(durationOf(1.nanoseconds), Duration.ZERO - durationOf((-1).nanoseconds))
assertEquals(Duration.MAX, durationOf((-1).seconds) - Duration.MIN)
}
@Test
fun `throws an exception when addition or subtraction of another duration causes overflow`() {
assertFailsWith { Duration.MAX + durationOf(1.nanoseconds) }
assertFailsWith { Duration.MAX - -durationOf(1.nanoseconds) }
assertFailsWith { Duration.MIN - durationOf(1.nanoseconds) }
assertFailsWith { Duration.MIN + -durationOf(1.nanoseconds) }
}
@Test
fun `multiplying by zero returns ZERO`() {
assertEquals(Duration.ZERO, 2.hours.asDuration() * 0)
}
@Test
fun `multiplying by 1 returns the same duration`() {
assertEquals(4.seconds.asDuration(), 4.seconds.asDuration() * 1)
assertEquals((-4).seconds.asDuration(), (-4).seconds.asDuration() * 1)
}
@Test
fun `multiplying by -1 reverses the sign of the duration`() {
assertEquals((-4).seconds.asDuration(), 4.seconds.asDuration() * -1)
assertEquals(4.seconds.asDuration(), (-4).seconds.asDuration() * -1)
}
@Test
fun `throws an exception when multiplication causes overflow`() {
assertFailsWith { Long.MIN_VALUE.seconds.asDuration() * -1 }
assertFailsWith { Int.MAX_VALUE.hours.asDuration() * Int.MAX_VALUE }
}
@Test
fun `multiplication by a positive scalar value`() {
assertEquals(
(25.hours + 2.seconds + 500.milliseconds).asDuration(),
5 * (5.hours + 500.milliseconds).asDuration()
)
}
@Test
fun `multiplication by a negative scalar value`() {
assertEquals(
((-25).hours - 2.seconds - 500.milliseconds).asDuration(),
(5.hours + 500.milliseconds).asDuration() * -5
)
}
@Test
fun `dividing by zero causes an exception`() {
assertFailsWith { durationOf(5.hours) / 0 }
}
@Test
fun `dividing by 1 returns the same duration`() {
assertEquals(1.minutes.asDuration(), 1.minutes.asDuration() / 1)
}
@Test
fun `dividing by -1 negates the duration`() {
assertEquals(1.minutes.asDuration(), (-1).minutes.asDuration() / -1)
}
@Test
fun `dividing by -1 causes an exception when the duration is at minimum`() {
assertFailsWith { Duration.MIN / -1 }
}
@Test
fun `division by a positive scalar value`() {
assertEquals(
111_111_111.nanoseconds.asDuration(),
1.seconds.asDuration() / 9
)
assertEquals(
durationOf(12.minutes + 1.nanoseconds),
durationOf(1.hours + 5.nanoseconds) / 5
)
}
@Test
fun `division by a negative scalar value`() {
assertEquals(
(-100).milliseconds.asDuration(),
1.seconds.asDuration() / -10
)
}
@Test
fun `toComponents() executes function with expected arguments`() {
durationOf(5.hours + 30.minutes + 30.seconds + 500.milliseconds)
.toComponents { hours, minutes, seconds, nanoseconds ->
assertEquals(5L.hours, hours)
assertEquals(30.minutes, minutes)
assertEquals(30.seconds, seconds)
assertEquals(500_000_000.nanoseconds, nanoseconds)
}
durationOf((-1).days - 1.hours - 1.minutes - 1.seconds - 800.milliseconds - 50.nanoseconds)
.toComponents { days, hours, minutes, seconds, nanoseconds ->
assertEquals((-1L).days, days)
assertEquals((-1).hours, hours)
assertEquals((-1).minutes, minutes)
assertEquals((-1).seconds, seconds)
assertEquals((-800_000_050).nanoseconds, nanoseconds)
}
}
@Test
fun `truncatedTo(DAYS) truncates the precision to 24-hour days`() {
assertEquals(
1.days.asDuration(),
durationOf(1.days + 1.hours + 1.nanoseconds).truncatedTo(DAYS)
)
assertEquals(
(-1).days.asDuration(),
durationOf((-1).days - 1.hours - 1.nanoseconds).truncatedTo(DAYS)
)
assertEquals(
Duration.ZERO,
durationOf(1.days - 1.nanoseconds).truncatedTo(DAYS)
)
assertEquals(
Duration.ZERO,
durationOf((-1).days + 1.nanoseconds).truncatedTo(DAYS)
)
}
@Test
fun `truncatedTo(HOURS) truncates the precision to hours`() {
assertEquals(
1.hours.asDuration(),
durationOf(1.hours + 1.minutes + 1.nanoseconds).truncatedTo(HOURS)
)
assertEquals(
(-1).hours.asDuration(),
durationOf((-1).hours - 1.minutes - 1.nanoseconds).truncatedTo(HOURS)
)
assertEquals(
Duration.ZERO,
durationOf(1.hours - 1.nanoseconds).truncatedTo(HOURS)
)
assertEquals(
Duration.ZERO,
durationOf((-1).hours + 1.nanoseconds).truncatedTo(HOURS)
)
}
@Test
fun `truncatedTo(MINUTES) truncates the precision to minutes`() {
assertEquals(
1.minutes.asDuration(),
durationOf(1.minutes + 1.seconds + 1.nanoseconds).truncatedTo(MINUTES)
)
assertEquals(
(-1).minutes.asDuration(),
durationOf((-1).minutes - 1.seconds - 1.nanoseconds).truncatedTo(MINUTES)
)
assertEquals(
Duration.ZERO,
durationOf(1.minutes - 1.nanoseconds).truncatedTo(MINUTES)
)
assertEquals(
Duration.ZERO,
durationOf((-1).minutes + 1.nanoseconds).truncatedTo(MINUTES)
)
}
@Test
fun `truncatedTo(SECONDS) truncates the precision to seconds`() {
assertEquals(
1.seconds.asDuration(),
durationOf(1.seconds + 1.nanoseconds).truncatedTo(SECONDS)
)
assertEquals(
(-1).seconds.asDuration(),
durationOf((-1).seconds - 1.nanoseconds).truncatedTo(SECONDS)
)
assertEquals(
Duration.ZERO,
durationOf(1.seconds - 1.nanoseconds).truncatedTo(SECONDS)
)
assertEquals(
Duration.ZERO,
durationOf((-1).seconds + 1.nanoseconds).truncatedTo(SECONDS)
)
}
@Test
fun `truncatedTo(MILLISECONDS) truncates the precision to milliseconds`() {
assertEquals(
1.milliseconds.asDuration(),
durationOf(1.milliseconds + 1.nanoseconds).truncatedTo(MILLISECONDS)
)
assertEquals(
(-1).milliseconds.asDuration(),
durationOf((-1).milliseconds - 1.nanoseconds).truncatedTo(MILLISECONDS)
)
assertEquals(
Duration.ZERO,
durationOf(1.milliseconds - 1.nanoseconds).truncatedTo(MILLISECONDS)
)
assertEquals(
Duration.ZERO,
durationOf((-1).milliseconds + 1.nanoseconds).truncatedTo(MILLISECONDS)
)
}
@Test
fun `truncatedTo(MICROSECONDS) truncates the precision to microseconds`() {
assertEquals(
1.microseconds.asDuration(),
durationOf(1.microseconds + 1.nanoseconds).truncatedTo(MICROSECONDS)
)
assertEquals(
(-1).microseconds.asDuration(),
durationOf((-1).microseconds - 1.nanoseconds).truncatedTo(MICROSECONDS)
)
assertEquals(
Duration.ZERO,
durationOf(1.microseconds - 1.nanoseconds).truncatedTo(MICROSECONDS)
)
assertEquals(
Duration.ZERO,
durationOf((-1).microseconds + 1.nanoseconds).truncatedTo(MICROSECONDS)
)
}
@Test
fun `absoluteValue returns the absolute value of a duration`() {
assertEquals(durationOf(30.seconds), durationOf(30.seconds).absoluteValue)
assertEquals(durationOf(30.seconds), durationOf((-30).seconds).absoluteValue)
}
@Test
fun `abs() returns the absolute value of a duration`() {
assertEquals(durationOf(30.seconds), abs(30.seconds.asDuration()))
assertEquals(durationOf(30.seconds), abs((-30).seconds.asDuration()))
}
@Test
fun `toString() converts zero durations to 'PT0S'`() {
assertEquals("PT0S", Duration.ZERO.toString())
}
@Test
fun `toString() converts positive durations to ISO-8601 duration representation`() {
assertEquals(
"PT25H30M30.5S",
durationOf(1.days + 1.hours + 30.minutes + 30.seconds + 500.milliseconds).toString()
)
assertEquals(
"PT0.005S",
durationOf(5.milliseconds).toString()
)
}
@Test
fun `toString() converts negative durations to ISO-8601 duration representation`() {
assertEquals(
"PT-25H-30M-30.5S",
durationOf((-1).days - 1.hours - 30.minutes - 30.seconds - 500.milliseconds).toString()
)
assertEquals(
"PT-0.005S",
durationOf((-5).milliseconds).toString()
)
}
@Test
fun `String_toDuration() throws an exception when string is empty`() {
assertFailsWith { "".toDuration() }
}
@Test
fun `String_toDuration() throws an exception when string is invalid`() {
assertFailsWith { "P4Y".toDuration() }
assertFailsWith { "P4M".toDuration() }
assertFailsWith { "PT4H ".toDuration() }
assertFailsWith { " PT4H".toDuration() }
assertFailsWith { "PT4S4H".toDuration() }
assertFailsWith { "PT9Y".toDuration() }
}
@Test
fun `String_toDuration() parses durations of zero`() {
assertEquals(Duration.ZERO, "P0D".toDuration())
assertEquals(Duration.ZERO, "PT0S".toDuration())
}
@Test
fun `String_toDuration() converts ISO-8601 period strings to a Duration`() {
assertEquals(
durationOf(1.seconds),
"PT1S".toDuration()
)
assertEquals(
durationOf(1.days),
"P1D".toDuration()
)
assertEquals(
durationOf(0.seconds, 1.nanoseconds),
"PT0.000000001S".toDuration()
)
assertEquals(
durationOf(1.hours + 1.seconds),
"PT1H1S".toDuration()
)
assertEquals(
durationOf(1.hours - 5.seconds - 200.milliseconds),
"PT1H-5.2S".toDuration()
)
}
@ExperimentalTime
@Test
fun `conversion to Kotlin Duration`() {
assertEquals(
1.000_000_100.kotlinSeconds,
durationOf(1.seconds, 100.nanoseconds).toKotlinDuration()
)
assertEquals(
(-1.000_000_100).kotlinSeconds,
durationOf((-1).seconds, (-100).nanoseconds).toKotlinDuration()
)
}
@ExperimentalTime
@Test
fun `conversion from Kotlin Duration`() {
assertEquals(
durationOf(5.seconds, 1.nanoseconds),
(5.kotlinSeconds + 1.kotlinNanoseconds).toIslandDuration()
)
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy