Skip to content

Commit 545f8a4

Browse files
committed
Make CalendarUnit an internal helper enum
Drop WEEK and introduce MILLISECOND and MICROSECOND
1 parent c719ba9 commit 545f8a4

File tree

15 files changed

+83
-70
lines changed

15 files changed

+83
-70
lines changed

core/commonMain/src/DateTimePeriod.kt

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -125,13 +125,3 @@ operator fun DatePeriod.plus(other: DatePeriod): DatePeriod = DatePeriod(
125125
this.days + other.days
126126
)
127127

128-
enum class CalendarUnit {
129-
YEAR,
130-
MONTH,
131-
WEEK,
132-
DAY,
133-
HOUR,
134-
MINUTE,
135-
SECOND,
136-
NANOSECOND
137-
}

core/commonMain/src/DateTimeUnit.kt

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,14 @@ sealed class DateTimeUnit {
3636
calendarUnit = CalendarUnit.SECOND
3737
calendarScale = nanoseconds / 1_000_000_000
3838
}
39+
nanoseconds % 1_000_000 == 0L -> {
40+
calendarUnit = CalendarUnit.MILLISECOND
41+
calendarScale = nanoseconds / 1_000_000
42+
}
43+
nanoseconds % 1_000 == 0L -> {
44+
calendarUnit = CalendarUnit.MICROSECOND
45+
calendarScale = nanoseconds / 1_000
46+
}
3947
else -> {
4048
calendarUnit = CalendarUnit.NANOSECOND
4149
calendarScale = nanoseconds
@@ -104,3 +112,16 @@ sealed class DateTimeUnit {
104112
val CENTURY = YEAR * 100
105113
}
106114
}
115+
116+
117+
internal enum class CalendarUnit {
118+
YEAR,
119+
MONTH,
120+
DAY,
121+
HOUR,
122+
MINUTE,
123+
SECOND,
124+
MILLISECOND,
125+
MICROSECOND,
126+
NANOSECOND
127+
}

core/commonMain/src/Instant.kt

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -79,12 +79,12 @@ public expect fun Instant.plus(period: DateTimePeriod, zone: TimeZone): Instant
7979
/**
8080
* @throws DateTimeArithmeticException if this value or the result is too large to fit in [LocalDateTime].
8181
*/
82-
public expect fun Instant.plus(value: Int, unit: CalendarUnit, zone: TimeZone): Instant
82+
internal expect fun Instant.plus(value: Int, unit: CalendarUnit, zone: TimeZone): Instant
8383

8484
/**
8585
* @throws DateTimeArithmeticException if this value or the result is too large to fit in [LocalDateTime].
8686
*/
87-
public expect fun Instant.plus(value: Long, unit: CalendarUnit, zone: TimeZone): Instant
87+
internal expect fun Instant.plus(value: Long, unit: CalendarUnit, zone: TimeZone): Instant
8888

8989
/**
9090
* @throws DateTimeArithmeticException if this [Instant] or [other] is too large to fit in [LocalDateTime].
@@ -97,7 +97,7 @@ public expect fun Instant.periodUntil(other: Instant, zone: TimeZone): DateTimeP
9797
*
9898
* @throws DateTimeArithmeticException if this [Instant] or [other] is too large to fit in [LocalDateTime].
9999
*/
100-
public expect fun Instant.until(other: Instant, unit: CalendarUnit, zone: TimeZone): Long
100+
internal expect fun Instant.until(other: Instant, unit: CalendarUnit, zone: TimeZone): Long
101101

102102
/**
103103
* The return value is clamped to [Int.MAX_VALUE] or [Int.MIN_VALUE] if the result would otherwise cause an arithmetic
@@ -131,7 +131,6 @@ internal fun Long.clampToInt(): Int =
131131
if (this > Int.MAX_VALUE) Int.MAX_VALUE else if (this < Int.MIN_VALUE) Int.MIN_VALUE else toInt()
132132

133133
public fun Instant.minus(other: Instant, zone: TimeZone): DateTimePeriod = other.periodUntil(this, zone)
134-
public fun Instant.minus(other: Instant, unit: CalendarUnit, zone: TimeZone): Long = other.until(this, unit, zone)
135134

136135

137136

core/commonMain/src/LocalDate.kt

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -38,13 +38,13 @@ public fun String.toLocalDate(): LocalDate = LocalDate.parse(this)
3838
* @throws IllegalArgumentException if the calendar unit is not date-based.
3939
* @throws DateTimeArithmeticException if the result exceeds the boundaries of [LocalDate].
4040
*/
41-
expect fun LocalDate.plus(value: Long, unit: CalendarUnit): LocalDate
41+
internal expect fun LocalDate.plus(value: Long, unit: CalendarUnit): LocalDate
4242

4343
/**
4444
* @throws IllegalArgumentException if the calendar unit is not date-based.
4545
* @throws DateTimeArithmeticException if the result exceeds the boundaries of [LocalDate].
4646
*/
47-
expect fun LocalDate.plus(value: Int, unit: CalendarUnit): LocalDate
47+
internal expect fun LocalDate.plus(value: Int, unit: CalendarUnit): LocalDate
4848

4949
/**
5050
* @throws IllegalArgumentException if [period] has non-zero time (as opposed to date) components.
@@ -63,15 +63,6 @@ public expect fun LocalDate.daysUntil(other: LocalDate): Int
6363
public expect fun LocalDate.monthsUntil(other: LocalDate): Int
6464
public expect fun LocalDate.yearsUntil(other: LocalDate): Int
6565

66-
public fun LocalDate.until(other: LocalDate, unit: CalendarUnit): Int = when(unit) {
67-
CalendarUnit.YEAR -> yearsUntil(other)
68-
CalendarUnit.MONTH -> monthsUntil(other)
69-
CalendarUnit.WEEK -> daysUntil(other) / 7
70-
CalendarUnit.DAY -> daysUntil(other)
71-
CalendarUnit.HOUR, CalendarUnit.MINUTE, CalendarUnit.SECOND, CalendarUnit.NANOSECOND ->
72-
throw UnsupportedOperationException("Only date based units can be used to express difference between LocalDate values.")
73-
}
74-
7566
public fun LocalDate.plus(unit: DateTimeUnit.DateBased): LocalDate =
7667
plus(unit.calendarScale, unit.calendarUnit)
7768
public fun LocalDate.plus(value: Int, unit: DateTimeUnit.DateBased): LocalDate =

core/commonTest/src/InstantTest.kt

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -91,15 +91,15 @@ class InstantTest {
9191
val instant2 = instant1.plus(DateTimePeriod(hours = 24), zone)
9292
checkComponents(instant2.toLocalDateTime(zone), 2019, 10, 28, 1, 59)
9393
assertEquals(24.hours, instant2 - instant1)
94-
assertEquals(24, instant1.until(instant2, CalendarUnit.HOUR, zone))
95-
assertEquals(24, instant2.minus(instant1, CalendarUnit.HOUR, zone))
94+
assertEquals(24, instant1.until(instant2, DateTimeUnit.HOUR, zone))
95+
assertEquals(24, instant2.minus(instant1, DateTimeUnit.HOUR, zone))
9696

9797
val instant3 = instant1.plus(DateTimeUnit.DAY, zone)
9898
checkComponents(instant3.toLocalDateTime(zone), 2019, 10, 28, 2, 59)
9999
assertEquals(25.hours, instant3 - instant1)
100-
assertEquals(1, instant1.until(instant3, CalendarUnit.DAY, zone))
100+
assertEquals(1, instant1.until(instant3, DateTimeUnit.DAY, zone))
101101
assertEquals(1, instant1.daysUntil(instant3, zone))
102-
assertEquals(1, instant3.minus(instant1, CalendarUnit.DAY, zone))
102+
assertEquals(1, instant3.minus(instant1, DateTimeUnit.DAY, zone))
103103

104104
val instant4 = instant1.plus(14, DateTimeUnit.MONTH, zone)
105105
checkComponents(instant4.toLocalDateTime(zone), 2020, 12, 27, 2, 59)
@@ -110,8 +110,10 @@ class InstantTest {
110110
assertEquals(366 + 31 + 30, instant1.until(instant4, DateTimeUnit.DAY, zone))
111111
assertEquals((366 + 31 + 30) * 24 + 1, instant1.until(instant4, DateTimeUnit.HOUR, zone))
112112

113-
for (timeUnit in listOf(DateTimeUnit.SECOND, DateTimeUnit.MINUTE, DateTimeUnit.HOUR)) {
114-
assertEquals(instant4 - instant1, timeUnit.duration * instant4.minus(instant1, timeUnit, zone).toDouble())
113+
for (timeUnit in listOf(DateTimeUnit.MICROSECOND, DateTimeUnit.MILLISECOND, DateTimeUnit.SECOND, DateTimeUnit.MINUTE, DateTimeUnit.HOUR)) {
114+
val diff = instant4.minus(instant1, timeUnit, zone)
115+
assertEquals(instant4 - instant1, timeUnit.duration * diff.toDouble())
116+
assertEquals(instant4, instant1.plus(diff, timeUnit, zone))
115117
}
116118

117119
val period = DateTimePeriod(days = 1, hours = 1)

core/commonTest/src/LocalDateTest.kt

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -66,17 +66,16 @@ class LocalDateTest {
6666
checkComponents(LocalDate.parse("2016-01-31") + DatePeriod(months = 1), 2016, 2, 29)
6767

6868
// assertFailsWith<IllegalArgumentException> { startDate + CalendarPeriod(hours = 7) } // won't compile
69-
assertFailsWith<IllegalArgumentException> { startDate.plus(7, CalendarUnit.HOUR) }
7069
// assertFailsWith<IllegalArgumentException> { startDate.plus(7, ChronoUnit.MINUTE) } // won't compile
7170
}
7271

7372
@Test
7473
fun tomorrow() {
7574
val today = Clock.System.todayAt(TimeZone.SYSTEM)
7675

77-
val nextMonthPlusDay1 = today.plus(1, CalendarUnit.MONTH).plus(1, CalendarUnit.DAY)
76+
val nextMonthPlusDay1 = today.plus(DateTimeUnit.MONTH).plus(1, DateTimeUnit.DAY)
7877
val nextMonthPlusDay2 = today + DatePeriod(months = 1, days = 1)
79-
val nextMonthPlusDay3 = today.plus(1, CalendarUnit.DAY).plus(1, CalendarUnit.MONTH)
78+
val nextMonthPlusDay3 = today.plus(DateTimeUnit.DAY).plus(1, DateTimeUnit.MONTH)
8079
}
8180

8281
@Test
@@ -89,7 +88,7 @@ class LocalDateTest {
8988
val days1 = Random.nextInt(-3652..3652)
9089
val days2 = Random.nextInt(-3652..3652)
9190
val ldtBefore = origin + DatePeriod(days = days1)
92-
val ldtNow = origin.plus(days2, CalendarUnit.DAY)
91+
val ldtNow = origin.plus(days2, DateTimeUnit.DAY)
9392

9493
val diff = ldtNow - ldtBefore
9594
val ldtAfter = ldtBefore + diff
@@ -133,11 +132,6 @@ class LocalDateTest {
133132
}
134133
}
135134

136-
val d1 = LocalDate(2012, 6, 21)
137-
val d2 = LocalDate(2012, 7, 21)
138-
139-
for (unit in listOf(CalendarUnit.HOUR, CalendarUnit.MINUTE, CalendarUnit.SECOND, CalendarUnit.NANOSECOND))
140-
assertFailsWith<UnsupportedOperationException> { d1.until(d2, unit) }
141135
}
142136

143137
@Test

core/jsMain/src/Instant.kt

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -77,27 +77,29 @@ public actual fun Instant.plus(period: DateTimePeriod, zone: TimeZone): Instant
7777
}.toInstant().let(::Instant)
7878
}
7979

80-
public actual fun Instant.plus(value: Int, unit: CalendarUnit, zone: TimeZone): Instant =
80+
internal actual fun Instant.plus(value: Int, unit: CalendarUnit, zone: TimeZone): Instant =
8181
when (unit) {
8282
CalendarUnit.YEAR -> this.value.atZone(zone.zoneId).plusYears(value).toInstant()
8383
CalendarUnit.MONTH -> this.value.atZone(zone.zoneId).plusMonths(value).toInstant()
84-
CalendarUnit.WEEK -> this.value.atZone(zone.zoneId).plusWeeks(value).let { it as ZonedDateTime }.toInstant()
8584
CalendarUnit.DAY -> this.value.atZone(zone.zoneId).plusDays(value).let { it as ZonedDateTime }.toInstant()
8685
CalendarUnit.HOUR -> this.value.atZone(zone.zoneId).plusHours(value).toInstant()
8786
CalendarUnit.MINUTE -> this.value.atZone(zone.zoneId).plusMinutes(value).toInstant()
8887
CalendarUnit.SECOND -> this.value.plusSeconds(value)
88+
CalendarUnit.MILLISECOND -> this.value.plusMillis(value)
89+
CalendarUnit.MICROSECOND -> this.value.plusNanos(value * 1000)
8990
CalendarUnit.NANOSECOND -> this.value.plusNanos(value)
9091
}.let(::Instant)
9192

92-
public actual fun Instant.plus(value: Long, unit: CalendarUnit, zone: TimeZone): Instant =
93+
internal actual fun Instant.plus(value: Long, unit: CalendarUnit, zone: TimeZone): Instant =
9394
when (unit) {
9495
CalendarUnit.YEAR -> this.value.atZone(zone.zoneId).plusYears(value).toInstant()
9596
CalendarUnit.MONTH -> this.value.atZone(zone.zoneId).plusMonths(value).toInstant()
96-
CalendarUnit.WEEK -> this.value.atZone(zone.zoneId).plusWeeks(value).let { it as ZonedDateTime }.toInstant()
9797
CalendarUnit.DAY -> this.value.atZone(zone.zoneId).plusDays(value).let { it as ZonedDateTime }.toInstant()
9898
CalendarUnit.HOUR -> this.value.atZone(zone.zoneId).plusHours(value).toInstant()
9999
CalendarUnit.MINUTE -> this.value.atZone(zone.zoneId).plusMinutes(value).toInstant()
100100
CalendarUnit.SECOND -> this.value.plusSeconds(value)
101+
CalendarUnit.MILLISECOND -> this.value.plusMillis(value)
102+
CalendarUnit.MICROSECOND -> this.value.plusSeconds(value / 1_000_000).plusNanos((value % 1_000_000).toInt() * 1000)
101103
CalendarUnit.NANOSECOND -> this.value.plusNanos(value)
102104
}.let(::Instant)
103105

@@ -115,7 +117,7 @@ public actual fun Instant.periodUntil(other: Instant, zone: TimeZone): DateTimeP
115117
}
116118
}
117119

118-
actual fun Instant.until(other: Instant, unit: CalendarUnit, zone: TimeZone): Long =
120+
internal actual fun Instant.until(other: Instant, unit: CalendarUnit, zone: TimeZone): Long =
119121
until(other, unit.toChronoUnit(), zone.zoneId)
120122

121123
private fun Instant.until(other: Instant, unit: ChronoUnit, zone: ZoneId): Long =
@@ -124,10 +126,11 @@ private fun Instant.until(other: Instant, unit: ChronoUnit, zone: ZoneId): Long
124126
private fun CalendarUnit.toChronoUnit(): ChronoUnit = when(this) {
125127
CalendarUnit.YEAR -> ChronoUnit.YEARS
126128
CalendarUnit.MONTH -> ChronoUnit.MONTHS
127-
CalendarUnit.WEEK -> ChronoUnit.WEEKS
128129
CalendarUnit.DAY -> ChronoUnit.DAYS
129130
CalendarUnit.HOUR -> ChronoUnit.HOURS
130131
CalendarUnit.MINUTE -> ChronoUnit.MINUTES
131132
CalendarUnit.SECOND -> ChronoUnit.SECONDS
133+
CalendarUnit.MILLISECOND -> ChronoUnit.MILLIS
134+
CalendarUnit.MICROSECOND -> ChronoUnit.MICROS
132135
CalendarUnit.NANOSECOND -> ChronoUnit.NANOS
133136
}

core/jsMain/src/LocalDate.kt

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,18 +40,19 @@ private fun LocalDate.plusNumber(value: Number, unit: CalendarUnit): LocalDate =
4040
when (unit) {
4141
CalendarUnit.YEAR -> this.value.plusYears(value)
4242
CalendarUnit.MONTH -> this.value.plusMonths(value)
43-
CalendarUnit.WEEK -> this.value.plusWeeks(value)
4443
CalendarUnit.DAY -> this.value.plusDays(value)
4544
CalendarUnit.HOUR,
4645
CalendarUnit.MINUTE,
4746
CalendarUnit.SECOND,
47+
CalendarUnit.MILLISECOND,
48+
CalendarUnit.MICROSECOND,
4849
CalendarUnit.NANOSECOND -> throw IllegalArgumentException("Only date based units can be added to LocalDate")
4950
}.let(::LocalDate)
5051

51-
public actual fun LocalDate.plus(value: Long, unit: CalendarUnit): LocalDate =
52+
internal actual fun LocalDate.plus(value: Long, unit: CalendarUnit): LocalDate =
5253
plusNumber(value.toDouble(), unit)
5354

54-
public actual fun LocalDate.plus(value: Int, unit: CalendarUnit): LocalDate =
55+
internal actual fun LocalDate.plus(value: Int, unit: CalendarUnit): LocalDate =
5556
plusNumber(value, unit)
5657

5758

core/jvmMain/src/Instant.kt

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -71,18 +71,19 @@ public actual fun Instant.plus(period: DateTimePeriod, zone: TimeZone): Instant
7171
}.toInstant().let(::Instant)
7272
}
7373

74-
public actual fun Instant.plus(value: Int, unit: CalendarUnit, zone: TimeZone): Instant =
74+
internal actual fun Instant.plus(value: Int, unit: CalendarUnit, zone: TimeZone): Instant =
7575
plus(value.toLong(), unit, zone)
7676

77-
public actual fun Instant.plus(value: Long, unit: CalendarUnit, zone: TimeZone): Instant =
77+
internal actual fun Instant.plus(value: Long, unit: CalendarUnit, zone: TimeZone): Instant =
7878
when (unit) {
7979
CalendarUnit.YEAR -> this.value.atZone(zone.zoneId).plusYears(value).toInstant()
8080
CalendarUnit.MONTH -> this.value.atZone(zone.zoneId).plusMonths(value).toInstant()
81-
CalendarUnit.WEEK -> this.value.atZone(zone.zoneId).plusWeeks(value).toInstant()
8281
CalendarUnit.DAY -> this.value.atZone(zone.zoneId).plusDays(value).toInstant()
8382
CalendarUnit.HOUR -> this.value.atZone(zone.zoneId).plusHours(value).toInstant()
8483
CalendarUnit.MINUTE -> this.value.atZone(zone.zoneId).plusMinutes(value).toInstant()
8584
CalendarUnit.SECOND -> this.value.plusSeconds(value)
85+
CalendarUnit.MILLISECOND -> this.value.plusMillis(value)
86+
CalendarUnit.MICROSECOND -> this.value.plusSeconds(value / 1_000_000).plusNanos((value % 1_000_000) * 1000)
8687
CalendarUnit.NANOSECOND -> this.value.plusNanos(value)
8788
}.let(::Instant)
8889

@@ -100,7 +101,7 @@ public actual fun Instant.periodUntil(other: Instant, zone: TimeZone): DateTimeP
100101
}
101102
}
102103

103-
actual fun Instant.until(other: Instant, unit: CalendarUnit, zone: TimeZone): Long =
104+
internal actual fun Instant.until(other: Instant, unit: CalendarUnit, zone: TimeZone): Long =
104105
until(other, unit.toChronoUnit(), zone.zoneId)
105106

106107
private fun Instant.until(other: Instant, unit: ChronoUnit, zone: ZoneId): Long =
@@ -109,10 +110,11 @@ private fun Instant.until(other: Instant, unit: ChronoUnit, zone: ZoneId): Long
109110
private fun CalendarUnit.toChronoUnit(): ChronoUnit = when(this) {
110111
CalendarUnit.YEAR -> ChronoUnit.YEARS
111112
CalendarUnit.MONTH -> ChronoUnit.MONTHS
112-
CalendarUnit.WEEK -> ChronoUnit.WEEKS
113113
CalendarUnit.DAY -> ChronoUnit.DAYS
114114
CalendarUnit.HOUR -> ChronoUnit.HOURS
115115
CalendarUnit.MINUTE -> ChronoUnit.MINUTES
116116
CalendarUnit.SECOND -> ChronoUnit.SECONDS
117+
CalendarUnit.MILLISECOND -> ChronoUnit.MILLIS
118+
CalendarUnit.MICROSECOND -> ChronoUnit.MICROS
117119
CalendarUnit.NANOSECOND -> ChronoUnit.NANOS
118120
}

core/jvmMain/src/LocalDate.kt

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,19 +37,20 @@ public actual class LocalDate internal constructor(internal val value: jtLocalDa
3737
}
3838

3939

40-
public actual fun LocalDate.plus(value: Long, unit: CalendarUnit): LocalDate =
40+
internal actual fun LocalDate.plus(value: Long, unit: CalendarUnit): LocalDate =
4141
when (unit) {
4242
CalendarUnit.YEAR -> this.value.plusYears(value)
4343
CalendarUnit.MONTH -> this.value.plusMonths(value)
44-
CalendarUnit.WEEK -> this.value.plusWeeks(value)
4544
CalendarUnit.DAY -> this.value.plusDays(value)
4645
CalendarUnit.HOUR,
4746
CalendarUnit.MINUTE,
4847
CalendarUnit.SECOND,
48+
CalendarUnit.MILLISECOND,
49+
CalendarUnit.MICROSECOND,
4950
CalendarUnit.NANOSECOND -> throw IllegalArgumentException("Only date based units can be added to LocalDate")
5051
}.let(::LocalDate)
5152

52-
public actual fun LocalDate.plus(value: Int, unit: CalendarUnit): LocalDate =
53+
internal actual fun LocalDate.plus(value: Int, unit: CalendarUnit): LocalDate =
5354
plus(value.toLong(), unit)
5455

5556
public actual operator fun LocalDate.plus(period: DatePeriod): LocalDate =

0 commit comments

Comments
 (0)