Skip to content

Commit 72a15f6

Browse files
committed
Add tests and samples to kotlinx.time
1 parent ab531cc commit 72a15f6

File tree

9 files changed

+997
-3
lines changed

9 files changed

+997
-3
lines changed

fake-kotlinx-time/common/src/Instant.kt

+3-3
Original file line numberDiff line numberDiff line change
@@ -234,8 +234,6 @@ public class Instant internal constructor(
234234
* Returns zero if this instant represents the same moment as the other (meaning they are equal to one another),
235235
* a negative number if this instant is earlier than the other,
236236
* and a positive number if this instant is later than the other.
237-
*
238-
* @sample kotlinx.datetime.test.samples.InstantSamples.compareToSample
239237
*/
240238
public override operator fun compareTo(other: Instant): Int {
241239
val s = epochSeconds.compareTo(other.epochSeconds)
@@ -262,6 +260,8 @@ public class Instant internal constructor(
262260
* where the component for seconds is 60, and for any day, it's possible to observe 23:59:59.
263261
*
264262
* @see parse
263+
*
264+
* @sample kotlinx.datetime.test.samples.InstantSamples.toStringSample
265265
*/
266266
public override fun toString(): String = formatIso(this)
267267

@@ -748,7 +748,7 @@ private const val NANOS_PER_MILLI = 1_000_000
748748
private const val MILLIS_PER_ONE = 1_000
749749

750750
// org.threeten.bp.chrono.IsoChronology#isLeapYear
751-
private fun isLeapYear(year: Int): Boolean {
751+
internal fun isLeapYear(year: Int): Boolean {
752752
val prolepticYear: Long = year.toLong()
753753
return prolepticYear and 3 == 0L && (prolepticYear % 100 != 0L || prolepticYear % 400 == 0L)
754754
}

fake-kotlinx-time/common/test/InstantTest.kt

+608
Large diffs are not rendered by default.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
/*
2+
* Copyright 2019-2020 JetBrains s.r.o.
3+
* Use of this source code is governed by the Apache 2.0 License that can be found in the LICENSE.txt file.
4+
*/
5+
/* Based on the ThreeTenBp project.
6+
* Copyright (c) 2007-present, Stephen Colebourne & Michael Nascimento Santos
7+
*/
8+
9+
package kotlinx.time.test
10+
11+
import kotlinx.time.*
12+
import kotlin.test.*
13+
14+
class ThreeTenBpInstantTest {
15+
16+
@Test
17+
fun instantComparisons() {
18+
val instants = arrayOf(
19+
Instant.fromEpochSeconds(-2L, 0),
20+
Instant.fromEpochSeconds(-2L, 999999998),
21+
Instant.fromEpochSeconds(-2L, 999999999),
22+
Instant.fromEpochSeconds(-1L, 0),
23+
Instant.fromEpochSeconds(-1L, 1),
24+
Instant.fromEpochSeconds(-1L, 999999998),
25+
Instant.fromEpochSeconds(-1L, 999999999),
26+
Instant.fromEpochSeconds(0L, 0),
27+
Instant.fromEpochSeconds(0L, 1),
28+
Instant.fromEpochSeconds(0L, 2),
29+
Instant.fromEpochSeconds(0L, 999999999),
30+
Instant.fromEpochSeconds(1L, 0),
31+
Instant.fromEpochSeconds(2L, 0)
32+
)
33+
for (i in instants.indices) {
34+
val a = instants[i]
35+
for (j in instants.indices) {
36+
val b = instants[j]
37+
when {
38+
i < j -> {
39+
assertTrue(a < b, "$a <=> $b")
40+
assertNotEquals(a, b, "$a <=> $b")
41+
}
42+
i > j -> {
43+
assertTrue(a > b, "$a <=> $b")
44+
assertNotEquals(a, b, "$a <=> $b")
45+
}
46+
else -> {
47+
assertEquals(0, a.compareTo(b), "$a <=> $b")
48+
assertEquals(a, b, "$a <=> $b")
49+
}
50+
}
51+
}
52+
}
53+
}
54+
55+
@Test
56+
fun instantEquals() {
57+
val test5a: Instant = Instant.fromEpochSeconds(5L, 20)
58+
val test5b: Instant = Instant.fromEpochSeconds(5L, 20)
59+
val test5n: Instant = Instant.fromEpochSeconds(5L, 30)
60+
val test6: Instant = Instant.fromEpochSeconds(6L, 20)
61+
assertEquals(true, test5a == test5a)
62+
assertEquals(true, test5a == test5b)
63+
assertEquals(false, test5a == test5n)
64+
assertEquals(false, test5a == test6)
65+
assertEquals(true, test5b == test5a)
66+
assertEquals(true, test5b == test5b)
67+
assertEquals(false, test5b == test5n)
68+
assertEquals(false, test5b == test6)
69+
assertEquals(false, test5n == test5a)
70+
assertEquals(false, test5n == test5b)
71+
assertEquals(true, test5n == test5n)
72+
assertEquals(false, test5n == test6)
73+
assertEquals(false, test6 == test5a)
74+
assertEquals(false, test6 == test5b)
75+
assertEquals(false, test6 == test5n)
76+
assertEquals(true, test6 == test6)
77+
}
78+
79+
@Test
80+
fun toEpochMilliseconds() {
81+
assertEquals(Instant.fromEpochSeconds(1L, 1000000).toEpochMilliseconds(), 1001L)
82+
assertEquals(Instant.fromEpochSeconds(1L, 2000000).toEpochMilliseconds(), 1002L)
83+
assertEquals(Instant.fromEpochSeconds(1L, 567).toEpochMilliseconds(), 1000L)
84+
assertEquals(Instant.fromEpochSeconds(Long.MAX_VALUE / 1_000_000).toEpochMilliseconds(), Long.MAX_VALUE / 1_000_000 * 1000)
85+
assertEquals(Instant.fromEpochSeconds(Long.MIN_VALUE / 1_000_000).toEpochMilliseconds(), Long.MIN_VALUE / 1_000_000 * 1000)
86+
assertEquals(Instant.fromEpochSeconds(0L, -1000000).toEpochMilliseconds(), -1L)
87+
assertEquals(Instant.fromEpochSeconds(0L, 1000000).toEpochMilliseconds(), 1)
88+
assertEquals(Instant.fromEpochSeconds(0L, 999999).toEpochMilliseconds(), 0)
89+
assertEquals(Instant.fromEpochSeconds(0L, 1).toEpochMilliseconds(), 0)
90+
assertEquals(Instant.fromEpochSeconds(0L, 0).toEpochMilliseconds(), 0)
91+
assertEquals(Instant.fromEpochSeconds(0L, -1).toEpochMilliseconds(), -1L)
92+
assertEquals(Instant.fromEpochSeconds(0L, -999999).toEpochMilliseconds(), -1L)
93+
assertEquals(Instant.fromEpochSeconds(0L, -1000000).toEpochMilliseconds(), -1L)
94+
assertEquals(Instant.fromEpochSeconds(0L, -1000001).toEpochMilliseconds(), -2L)
95+
}
96+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/*
2+
* Copyright 2019-2020 JetBrains s.r.o.
3+
* Use of this source code is governed by the Apache 2.0 License that can be found in the LICENSE.txt file.
4+
*/
5+
/* Based on the ThreeTenBp project.
6+
* Copyright (c) 2007-present, Stephen Colebourne & Michael Nascimento Santos
7+
*/
8+
9+
package kotlinx.time.test
10+
11+
import kotlinx.time.*
12+
import kotlin.test.*
13+
14+
class ThreeTenBpUtilTest {
15+
@Test
16+
fun isLeap() {
17+
assertEquals(false, isLeapYear(1999))
18+
assertEquals(true, isLeapYear(2000))
19+
assertEquals(false, isLeapYear(2001))
20+
assertEquals(false, isLeapYear(2007))
21+
assertEquals(true, isLeapYear(2008))
22+
assertEquals(false, isLeapYear(2009))
23+
assertEquals(false, isLeapYear(2010))
24+
assertEquals(false, isLeapYear(2011))
25+
assertEquals(true, isLeapYear(2012))
26+
assertEquals(false, isLeapYear(2095))
27+
assertEquals(true, isLeapYear(2096))
28+
assertEquals(false, isLeapYear(2097))
29+
assertEquals(false, isLeapYear(2098))
30+
assertEquals(false, isLeapYear(2099))
31+
assertEquals(false, isLeapYear(2100))
32+
assertEquals(false, isLeapYear(2101))
33+
assertEquals(false, isLeapYear(2102))
34+
assertEquals(false, isLeapYear(2103))
35+
assertEquals(true, isLeapYear(2104))
36+
assertEquals(false, isLeapYear(2105))
37+
assertEquals(false, isLeapYear(-500))
38+
assertEquals(true, isLeapYear(-400))
39+
assertEquals(false, isLeapYear(-300))
40+
assertEquals(false, isLeapYear(-200))
41+
assertEquals(false, isLeapYear(-100))
42+
assertEquals(true, isLeapYear(0))
43+
assertEquals(false, isLeapYear(100))
44+
assertEquals(false, isLeapYear(200))
45+
assertEquals(false, isLeapYear(300))
46+
assertEquals(true, isLeapYear(400))
47+
assertEquals(false, isLeapYear(500))
48+
}
49+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/*
2+
* Copyright 2019-2021 JetBrains s.r.o.
3+
* Use of this source code is governed by the Apache 2.0 License that can be found in the LICENSE.txt file.
4+
*/
5+
package kotlinx.time.test
6+
7+
import kotlin.test.assertFailsWith
8+
import kotlin.test.fail
9+
10+
inline fun <T> assertInvalidFormat(message: String? = null, f: () -> T) {
11+
assertFailsWith<IllegalArgumentException>(message) {
12+
val result = f()
13+
fail(result.toString())
14+
}
15+
}
16+
17+
/**
18+
* The number of iterations to perform in nondeterministic tests.
19+
*/
20+
const val STRESS_TEST_ITERATIONS = 1000
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/*
2+
* Copyright 2019-2024 JetBrains s.r.o. and contributors.
3+
* Use of this source code is governed by the Apache 2.0 License that can be found in the LICENSE.txt file.
4+
*/
5+
6+
package kotlinx.datetime.test.samples
7+
8+
import kotlinx.time.*
9+
import kotlin.test.*
10+
11+
class ClockSamples {
12+
@Test
13+
fun system() {
14+
// Getting the current date and time
15+
val currentInstant = Clock.System.now()
16+
currentInstant.toEpochMilliseconds() // the number of milliseconds since the Unix epoch
17+
}
18+
19+
@Test
20+
fun dependencyInjection() {
21+
fun formatCurrentTime(clock: Clock): String =
22+
clock.now().toString()
23+
24+
// In the production code:
25+
val currentTimeInProduction = formatCurrentTime(Clock.System)
26+
// Testing this value is tricky because it changes all the time.
27+
28+
// In the test code:
29+
val testClock = object: Clock {
30+
override fun now(): Instant = Instant.parse("2023-01-02T22:35:01Z")
31+
}
32+
// Then, one can write a completely deterministic test:
33+
val currentTimeForTests = formatCurrentTime(testClock)
34+
check(currentTimeForTests == "2023-01-02T22:35:01Z")
35+
}
36+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
/*
2+
* Copyright 2019-2024 JetBrains s.r.o. and contributors.
3+
* Use of this source code is governed by the Apache 2.0 License that can be found in the LICENSE.txt file.
4+
*/
5+
6+
package kotlinx.datetime.test.samples
7+
8+
import kotlinx.time.*
9+
import kotlin.random.*
10+
import kotlin.test.*
11+
import kotlin.time.Duration.Companion.hours
12+
13+
class InstantSamples {
14+
15+
@Test
16+
fun epochSeconds() {
17+
// Getting the number of whole seconds that passed since the Unix epoch
18+
val instant1 = Instant.fromEpochSeconds(999_999, nanosecondAdjustment = 123_456_789)
19+
check(instant1.epochSeconds == 999_999L)
20+
val instant2 = Instant.fromEpochSeconds(1_000_000, nanosecondAdjustment = 100_123_456_789)
21+
check(instant2.epochSeconds == 1_000_000 + 100L)
22+
val instant3 = Instant.fromEpochSeconds(1_000_000, nanosecondAdjustment = -100_876_543_211)
23+
check(instant3.epochSeconds == 1_000_000 - 101L)
24+
}
25+
26+
@Test
27+
fun nanosecondsOfSecond() {
28+
// Getting the number of nanoseconds that passed since the start of the second
29+
val instant1 = Instant.fromEpochSeconds(999_999, nanosecondAdjustment = 123_456_789)
30+
check(instant1.nanosecondsOfSecond == 123_456_789)
31+
val instant2 = Instant.fromEpochSeconds(1_000_000, nanosecondAdjustment = 100_123_456_789)
32+
check(instant2.nanosecondsOfSecond == 123_456_789)
33+
val instant3 = Instant.fromEpochSeconds(1_000_000, nanosecondAdjustment = -100_876_543_211)
34+
check(instant3.nanosecondsOfSecond == 123_456_789)
35+
}
36+
37+
@Test
38+
fun toEpochMilliseconds() {
39+
// Converting an Instant to the number of milliseconds since the Unix epoch
40+
check(Instant.fromEpochMilliseconds(0).toEpochMilliseconds() == 0L)
41+
check(Instant.fromEpochMilliseconds(1_000_000_000_123).toEpochMilliseconds() == 1_000_000_000_123L)
42+
check(Instant.fromEpochSeconds(1_000_000_000, nanosecondAdjustment = 123_999_999)
43+
.toEpochMilliseconds() == 1_000_000_000_123L)
44+
}
45+
46+
@Test
47+
fun plusDuration() {
48+
// Finding a moment that's later than the starting point by the given amount of real time
49+
val instant = Instant.fromEpochSeconds(7 * 60 * 60, nanosecondAdjustment = 123_456_789)
50+
val fiveHoursLater = instant + 5.hours
51+
check(fiveHoursLater.epochSeconds == 12 * 60 * 60L)
52+
check(fiveHoursLater.nanosecondsOfSecond == 123_456_789)
53+
}
54+
55+
@Test
56+
fun minusDuration() {
57+
// Finding a moment that's earlier than the starting point by the given amount of real time
58+
val instant = Instant.fromEpochSeconds(7 * 60 * 60, nanosecondAdjustment = 123_456_789)
59+
val fiveHoursEarlier = instant - 5.hours
60+
check(fiveHoursEarlier.epochSeconds == 2 * 60 * 60L)
61+
check(fiveHoursEarlier.nanosecondsOfSecond == 123_456_789)
62+
}
63+
64+
@Test
65+
fun minusInstant() {
66+
// Finding the difference between two instants in terms of elapsed time
67+
check(Instant.fromEpochSeconds(0) - Instant.fromEpochSeconds(epochSeconds = 7 * 60 * 60) == (-7).hours)
68+
}
69+
70+
@Test
71+
fun toStringSample() {
72+
// Converting an Instant to a string
73+
check(Instant.fromEpochSeconds(0).toString() == "1970-01-01T00:00:00Z")
74+
}
75+
76+
@Test
77+
fun fromEpochMilliseconds() {
78+
// Constructing an Instant from the number of milliseconds since the Unix epoch
79+
check(Instant.fromEpochMilliseconds(epochMilliseconds = 0) == Instant.parse("1970-01-01T00:00:00Z"))
80+
check(Instant.fromEpochMilliseconds(epochMilliseconds = 1_000_000_000_123)
81+
== Instant.parse("2001-09-09T01:46:40.123Z"))
82+
}
83+
84+
@Test
85+
fun fromEpochSeconds() {
86+
// Constructing an Instant from the number of seconds and nanoseconds since the Unix epoch
87+
check(Instant.fromEpochSeconds(epochSeconds = 0) == Instant.parse("1970-01-01T00:00:00Z"))
88+
check(Instant.fromEpochSeconds(epochSeconds = 1_000_001_234, nanosecondAdjustment = -1_234_000_000_001)
89+
== Instant.parse("2001-09-09T01:46:39.999999999Z"))
90+
}
91+
92+
@Test
93+
fun fromEpochSecondsIntNanos() {
94+
// Constructing an Instant from the number of seconds and nanoseconds since the Unix epoch
95+
check(Instant.fromEpochSeconds(epochSeconds = 0) == Instant.parse("1970-01-01T00:00:00Z"))
96+
check(Instant.fromEpochSeconds(epochSeconds = 1_000_000_000, nanosecondAdjustment = -1) == Instant.parse("2001-09-09T01:46:39.999999999Z"))
97+
}
98+
99+
@Test
100+
fun parsing() {
101+
// Parsing an Instant from a string
102+
check(Instant.parse("1970-01-01T00:00:00Z") == Instant.fromEpochSeconds(0))
103+
}
104+
105+
@Test
106+
fun isDistantPast() {
107+
// Checking if an instant is so far in the past that it's probably irrelevant
108+
val currentInstant = Clock.System.now()
109+
val tenThousandYearsAgo = currentInstant.minus(24.hours * 365 * 1_000)
110+
check(!tenThousandYearsAgo.isDistantPast)
111+
check(Instant.DISTANT_PAST.isDistantPast)
112+
}
113+
114+
@Test
115+
fun isDistantFuture() {
116+
// Checking if an instant is so far in the future that it's probably irrelevant
117+
val currentInstant = Clock.System.now()
118+
val tenThousandYearsLater = currentInstant.plus(24.hours * 365 * 10_000)
119+
check(!tenThousandYearsLater.isDistantFuture)
120+
check(Instant.DISTANT_FUTURE.isDistantFuture)
121+
}
122+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/*
2+
* Copyright 2019-2022 JetBrains s.r.o. and contributors.
3+
* Use of this source code is governed by the Apache 2.0 License that can be found in the LICENSE.txt file.
4+
*/
5+
6+
package kotlinx.time.test
7+
8+
import kotlinx.time.*
9+
import kotlin.js.Date
10+
import kotlin.test.*
11+
12+
class ConvertersTest {
13+
@Test
14+
fun toJSDateTest() {
15+
val releaseInstant = Instant.parse("2016-02-15T00:00:00Z")
16+
val releaseDate = releaseInstant.toJSDate()
17+
assertEquals(2016, releaseDate.getUTCFullYear())
18+
assertEquals(1, releaseDate.getUTCMonth())
19+
assertEquals(15, releaseDate.getUTCDate())
20+
}
21+
22+
@Test
23+
fun toInstantTest() {
24+
val kotlinReleaseEpochMilliseconds = 1455494400000
25+
val releaseDate = Date(milliseconds = kotlinReleaseEpochMilliseconds)
26+
val releaseInstant = Instant.parse("2016-02-15T00:00:00Z")
27+
assertEquals(releaseInstant, releaseDate.toKotlinInstant())
28+
}
29+
}

0 commit comments

Comments
 (0)