diff --git a/core/common/src/DayOfWeek.kt b/core/common/src/DayOfWeek.kt index 496d61bef..0b7410235 100644 --- a/core/common/src/DayOfWeek.kt +++ b/core/common/src/DayOfWeek.kt @@ -8,7 +8,7 @@ package kotlinx.datetime /** * The enumeration class representing the days of the week. */ -public expect enum class DayOfWeek { +public enum class DayOfWeek { MONDAY, TUESDAY, WEDNESDAY, diff --git a/core/common/src/Month.kt b/core/common/src/Month.kt index 5603dc285..d92a793f8 100644 --- a/core/common/src/Month.kt +++ b/core/common/src/Month.kt @@ -8,7 +8,7 @@ package kotlinx.datetime /** * The enumeration class representing the 12 months of the year. */ -public expect enum class Month { +public enum class Month { /** January, month #01, with 31 days. */ JANUARY, diff --git a/core/common/test/DayOfWeekTest.kt b/core/common/test/DayOfWeekTest.kt index cbdb252aa..5ed0a0b03 100644 --- a/core/common/test/DayOfWeekTest.kt +++ b/core/common/test/DayOfWeekTest.kt @@ -19,4 +19,19 @@ class DayOfWeekTest { assertFailsWith { DayOfWeek(8) } assertFailsWith { DayOfWeek(Int.MIN_VALUE) } } -} \ No newline at end of file + + @Test + fun testExhaustiveWhenDayOfWeek() { + for (dayOfWeek in DayOfWeek.entries) { + when (dayOfWeek) { + DayOfWeek.MONDAY -> assertEquals(1, dayOfWeek.isoDayNumber) + DayOfWeek.TUESDAY -> assertEquals(2, dayOfWeek.isoDayNumber) + DayOfWeek.WEDNESDAY -> assertEquals(3, dayOfWeek.isoDayNumber) + DayOfWeek.THURSDAY -> assertEquals(4, dayOfWeek.isoDayNumber) + DayOfWeek.FRIDAY -> assertEquals(5, dayOfWeek.isoDayNumber) + DayOfWeek.SATURDAY -> assertEquals(6, dayOfWeek.isoDayNumber) + DayOfWeek.SUNDAY -> assertEquals(7, dayOfWeek.isoDayNumber) + } + } + } +} diff --git a/core/common/test/MonthTest.kt b/core/common/test/MonthTest.kt new file mode 100644 index 000000000..4bf85a6a2 --- /dev/null +++ b/core/common/test/MonthTest.kt @@ -0,0 +1,31 @@ +/* + * Copyright 2019-2024 JetBrains s.r.o. and contributors. + * Use of this source code is governed by the Apache 2.0 License that can be found in the LICENSE.txt file. + */ + +package kotlinx.datetime.test + +import kotlinx.datetime.* +import kotlin.test.* + +class MonthTest { + @Test + fun testExhaustiveWhen() { + for (month in Month.entries) { + when (month) { + Month.JANUARY -> assertEquals(1, month.number) + Month.FEBRUARY -> assertEquals(2, month.number) + Month.MARCH -> assertEquals(3, month.number) + Month.APRIL -> assertEquals(4, month.number) + Month.MAY -> assertEquals(5, month.number) + Month.JUNE -> assertEquals(6, month.number) + Month.JULY -> assertEquals(7, month.number) + Month.AUGUST -> assertEquals(8, month.number) + Month.SEPTEMBER -> assertEquals(9, month.number) + Month.OCTOBER -> assertEquals(10, month.number) + Month.NOVEMBER -> assertEquals(11, month.number) + Month.DECEMBER -> assertEquals(12, month.number) + } + } + } +} diff --git a/core/commonJs/src/DayOfWeek.kt b/core/commonJs/src/DayOfWeek.kt index aff66bbbe..8ac1b1973 100644 --- a/core/commonJs/src/DayOfWeek.kt +++ b/core/commonJs/src/DayOfWeek.kt @@ -7,14 +7,4 @@ package kotlinx.datetime import kotlinx.datetime.internal.JSJoda.DayOfWeek as jsDayOfWeek -public actual enum class DayOfWeek { - MONDAY, - TUESDAY, - WEDNESDAY, - THURSDAY, - FRIDAY, - SATURDAY, - SUNDAY; -} - -internal fun jsDayOfWeek.toDayOfWeek(): DayOfWeek = DayOfWeek(this.value()) \ No newline at end of file +internal fun jsDayOfWeek.toDayOfWeek(): DayOfWeek = DayOfWeek(this.value()) diff --git a/core/commonJs/src/Month.kt b/core/commonJs/src/Month.kt index ae113dac8..a68a808d2 100644 --- a/core/commonJs/src/Month.kt +++ b/core/commonJs/src/Month.kt @@ -7,19 +7,4 @@ package kotlinx.datetime import kotlinx.datetime.internal.JSJoda.Month as jsMonth -public actual enum class Month { - JANUARY, - FEBRUARY, - MARCH, - APRIL, - MAY, - JUNE, - JULY, - AUGUST, - SEPTEMBER, - OCTOBER, - NOVEMBER, - DECEMBER; -} - -internal fun jsMonth.toMonth(): Month = Month(this.value()) \ No newline at end of file +internal fun jsMonth.toMonth(): Month = Month(this.value()) diff --git a/core/jvm/src/Converters.kt b/core/jvm/src/Converters.kt index 6db8339d3..688b0f84a 100644 --- a/core/jvm/src/Converters.kt +++ b/core/jvm/src/Converters.kt @@ -93,3 +93,22 @@ public fun UtcOffset.toJavaZoneOffset(): java.time.ZoneOffset = this.zoneOffset */ public fun java.time.ZoneOffset.toKotlinUtcOffset(): UtcOffset = UtcOffset(this) +/** + * Converts this [kotlinx.datetime.Month][Month] value to a [java.time.Month][java.time.Month] value. + */ +public fun Month.toJavaMonth(): java.time.Month = java.time.Month.of(number) + +/** + * Converts this [java.time.Month][java.time.Month] value to a [kotlinx.datetime.Month][Month] value. + */ +public fun java.time.Month.toKotlinMonth(): Month = Month.entries[this.value - 1] + +/** + * Converts this [kotlinx.datetime.DayOfWeek][DayOfWeek] value to a [java.time.DayOfWeek][java.time.DayOfWeek] value. + */ +public fun DayOfWeek.toJavaDayOfWeek(): java.time.DayOfWeek = java.time.DayOfWeek.of(isoDayNumber) + +/** + * Converts this [java.time.DayOfWeek][java.time.DayOfWeek] value to a [kotlinx.datetime.DayOfWeek][DayOfWeek] value. + */ +public fun java.time.DayOfWeek.toKotlinDayOfWeek(): DayOfWeek = DayOfWeek.entries[this.value - 1] diff --git a/core/jvm/src/LocalDate.kt b/core/jvm/src/LocalDate.kt index fe3b9ae1a..a61383a7f 100644 --- a/core/jvm/src/LocalDate.kt +++ b/core/jvm/src/LocalDate.kt @@ -61,9 +61,9 @@ public actual class LocalDate internal constructor(internal val value: jtLocalDa public actual val year: Int get() = value.year public actual val monthNumber: Int get() = value.monthValue - public actual val month: Month get() = value.month + public actual val month: Month get() = value.month.toKotlinMonth() public actual val dayOfMonth: Int get() = value.dayOfMonth - public actual val dayOfWeek: DayOfWeek get() = value.dayOfWeek + public actual val dayOfWeek: DayOfWeek get() = value.dayOfWeek.toKotlinDayOfWeek() public actual val dayOfYear: Int get() = value.dayOfYear override fun equals(other: Any?): Boolean = @@ -78,6 +78,13 @@ public actual class LocalDate internal constructor(internal val value: jtLocalDa public actual fun toEpochDays(): Int = value.toEpochDay().clampToInt() } +@Deprecated( + "Use kotlinx.datetime.Month", + ReplaceWith("LocalDate(year, month.toKotlinMonth(), dayOfMonth)") +) +public fun LocalDate(year: Int, month: java.time.Month, dayOfMonth: Int): LocalDate = + LocalDate(year, month.toKotlinMonth(), dayOfMonth) + @Deprecated("Use the plus overload with an explicit number of units", ReplaceWith("this.plus(1, unit)")) public actual fun LocalDate.plus(unit: DateTimeUnit.DateBased): LocalDate = plus(1L, unit) @@ -149,3 +156,6 @@ public actual fun LocalDate.monthsUntil(other: LocalDate): Int = public actual fun LocalDate.yearsUntil(other: LocalDate): Int = this.value.until(other.value, ChronoUnit.YEARS).clampToInt() + +@Deprecated("Use kotlinx.datetime.Month", ReplaceWith("toKotlinMonth().number")) +public val java.time.Month.number: Int get() = toKotlinMonth().number diff --git a/core/jvm/src/LocalDateTime.kt b/core/jvm/src/LocalDateTime.kt index 7dc28cdb1..bbf877f0b 100644 --- a/core/jvm/src/LocalDateTime.kt +++ b/core/jvm/src/LocalDateTime.kt @@ -12,9 +12,6 @@ import java.time.DateTimeException import java.time.format.DateTimeParseException import java.time.LocalDateTime as jtLocalDateTime -public actual typealias Month = java.time.Month -public actual typealias DayOfWeek = java.time.DayOfWeek - @Serializable(with = LocalDateTimeIso8601Serializer::class) public actual class LocalDateTime internal constructor(internal val value: jtLocalDateTime) : Comparable { @@ -33,9 +30,9 @@ public actual class LocalDateTime internal constructor(internal val value: jtLoc public actual val year: Int get() = value.year public actual val monthNumber: Int get() = value.monthValue - public actual val month: Month get() = value.month + public actual val month: Month get() = value.month.toKotlinMonth() public actual val dayOfMonth: Int get() = value.dayOfMonth - public actual val dayOfWeek: DayOfWeek get() = value.dayOfWeek + public actual val dayOfWeek: DayOfWeek get() = value.dayOfWeek.toKotlinDayOfWeek() public actual val dayOfYear: Int get() = value.dayOfYear public actual val hour: Int get() = value.hour @@ -85,3 +82,24 @@ public actual class LocalDateTime internal constructor(internal val value: jtLoc } +@Deprecated( + "Use kotlinx.datetime.Month", + ReplaceWith("LocalDateTime(year, month.toKotlinMonth(), dayOfMonth, hour, minute, second, nanosecond)") +) +public fun LocalDateTime( + year: Int, + month: java.time.Month, + dayOfMonth: Int, + hour: Int, + minute: Int, + second: Int = 0, + nanosecond: Int = 0 +): LocalDateTime = LocalDateTime( + year, + month.toKotlinMonth(), + dayOfMonth, + hour, + minute, + second, + nanosecond +) diff --git a/core/jvm/src/LocalTime.kt b/core/jvm/src/LocalTime.kt index 71052570f..6767e2e1e 100644 --- a/core/jvm/src/LocalTime.kt +++ b/core/jvm/src/LocalTime.kt @@ -90,3 +90,10 @@ public actual class LocalTime internal constructor(internal val value: jtLocalTi } } + +@Deprecated( + "Use kotlinx.datetime.Month", + ReplaceWith("atDate(year, month.toKotlinMonth(), dayOfMonth)") +) +public fun LocalTime.atDate(year: Int, month: java.time.Month, dayOfMonth: Int = 0): LocalDateTime = + atDate(year, month.toKotlinMonth(), dayOfMonth) diff --git a/core/jvm/test/ConvertersTest.kt b/core/jvm/test/ConvertersTest.kt index 18d759938..f07a8d60f 100644 --- a/core/jvm/test/ConvertersTest.kt +++ b/core/jvm/test/ConvertersTest.kt @@ -26,7 +26,7 @@ class ConvertersTest { assertEquals(ktInstant, jtInstant.toKotlinInstant()) assertEquals(jtInstant, ktInstant.toJavaInstant()) - assertEquals(ktInstant, jtInstant.toString().toInstant()) + assertEquals(ktInstant, jtInstant.toString().let(Instant::parse)) assertEquals(jtInstant, ktInstant.toString().let(JTInstant::parse)) } @@ -40,7 +40,7 @@ class ConvertersTest { private fun randomDate(): LocalDate { val year = Random.nextInt(-20000, 20000) val month = Month.entries.random() - val day = (1..java.time.YearMonth.of(year, month).lengthOfMonth()).random() + val day = (1..java.time.YearMonth.of(year, month.toJavaMonth()).lengthOfMonth()).random() return LocalDate(year, month.number, day) } @@ -61,12 +61,14 @@ class ConvertersTest { @Test fun localDateTime() { fun test(ktDateTime: LocalDateTime) { - val jtDateTime = with(ktDateTime) { JTLocalDateTime.of(year, month, dayOfMonth, hour, minute, second, nanosecond) } + val jtDateTime = with(ktDateTime) { + JTLocalDateTime.of(year, month.toJavaMonth(), dayOfMonth, hour, minute, second, nanosecond) + } assertEquals(ktDateTime, jtDateTime.toKotlinLocalDateTime()) assertEquals(jtDateTime, ktDateTime.toJavaLocalDateTime()) - assertEquals(ktDateTime, jtDateTime.toString().toLocalDateTime()) + assertEquals(ktDateTime, jtDateTime.toString().let(LocalDateTime::parse)) assertEquals(jtDateTime, ktDateTime.toString().let(JTLocalDateTime::parse)) } @@ -83,7 +85,7 @@ class ConvertersTest { assertEquals(ktTime, jtTime.toKotlinLocalTime()) assertEquals(jtTime, ktTime.toJavaLocalTime()) - assertEquals(ktTime, jtTime.toString().toLocalTime()) + assertEquals(ktTime, jtTime.toString().let(LocalTime::parse)) assertEquals(jtTime, ktTime.toString().let(JTLocalTime::parse)) } @@ -95,12 +97,12 @@ class ConvertersTest { @Test fun localDate() { fun test(ktDate: LocalDate) { - val jtDate = with(ktDate) { JTLocalDate.of(year, month, dayOfMonth) } + val jtDate = with(ktDate) { JTLocalDate.of(year, month.toJavaMonth(), dayOfMonth) } assertEquals(ktDate, jtDate.toKotlinLocalDate()) assertEquals(jtDate, ktDate.toJavaLocalDate()) - assertEquals(ktDate, jtDate.toString().toLocalDate()) + assertEquals(ktDate, jtDate.toString().let(LocalDate::parse)) assertEquals(jtDate, ktDate.toString().let(JTLocalDate::parse)) } @@ -187,4 +189,26 @@ class ConvertersTest { test("+08") test("-103030") } + + @Test + fun month() { + fun test(month: Month) { + val jtMonth = month.toJavaMonth() + assertEquals(month, jtMonth.toKotlinMonth()) + assertEquals(month.name, jtMonth.name) + } + Month.entries.forEach(::test) + assertEquals(Month.JANUARY, java.time.Month.JANUARY.toKotlinMonth()) + } + + @Test + fun dayOfWeek() { + fun test(dayOfWeek: DayOfWeek) { + val jtDayOfWeek = dayOfWeek.toJavaDayOfWeek() + assertEquals(dayOfWeek, jtDayOfWeek.toKotlinDayOfWeek()) + assertEquals(dayOfWeek.name, jtDayOfWeek.name) + } + DayOfWeek.entries.forEach(::test) + assertEquals(DayOfWeek.MONDAY, java.time.DayOfWeek.MONDAY.toKotlinDayOfWeek()) + } } diff --git a/core/jvm/test/DeprecationReplacements.kt b/core/jvm/test/DeprecationReplacements.kt new file mode 100644 index 000000000..d0c807fd5 --- /dev/null +++ b/core/jvm/test/DeprecationReplacements.kt @@ -0,0 +1,33 @@ +/* + * Copyright 2019-2024 JetBrains s.r.o. and contributors. + * Use of this source code is governed by the Apache 2.0 License that can be found in the LICENSE.txt file. + */ +package kotlinx.datetime.test + +import kotlinx.datetime.* + +/** + * To test the deprecation replacements, remove the `Suppress` annotation and try automatically replacing the deprecated + * API usages with the new ones. + */ +@Suppress("DEPRECATION") +class DeprecationReplacements { + fun localTimeAtDate() { + LocalTime(18, 43, 15, 100500000) + .atDate(2023, java.time.Month.JANUARY, 20) + } + + fun monthNumber() { + java.time.Month.JANUARY.number + } + + fun localDateConstruction() { + LocalDate(2023, java.time.Month.JANUARY, 20) + } + + fun localDateTimeConstruction() { + LocalDateTime(2023, java.time.Month.JANUARY, 20, 18, 43, 15, 100500000) + LocalDateTime(2023, java.time.Month.JANUARY, 20, 18, 43, 15) + LocalDateTime(2023, java.time.Month.JANUARY, 20, 18, 43) + } +} diff --git a/core/native/src/Instant.kt b/core/native/src/Instant.kt index 70e0017be..6789f3064 100644 --- a/core/native/src/Instant.kt +++ b/core/native/src/Instant.kt @@ -16,16 +16,6 @@ import kotlin.time.* import kotlin.time.Duration.Companion.nanoseconds import kotlin.time.Duration.Companion.seconds -public actual enum class DayOfWeek { - MONDAY, - TUESDAY, - WEDNESDAY, - THURSDAY, - FRIDAY, - SATURDAY, - SUNDAY; -} - /** * The minimum supported epoch second. */ diff --git a/core/native/src/Month.kt b/core/native/src/Month.kt index fa5995cca..eaebe26eb 100644 --- a/core/native/src/Month.kt +++ b/core/native/src/Month.kt @@ -5,10 +5,6 @@ package kotlinx.datetime -public actual enum class Month { - JANUARY, FEBRUARY, MARCH, APRIL, MAY, JUNE, JULY, AUGUST, SEPTEMBER, OCTOBER, NOVEMBER, DECEMBER; -} - // From threetenbp internal fun Month.firstDayOfYear(leapYear: Boolean): Int { val leap = if (leapYear) 1 else 0