Just setting off on trying to learn some Kotlin I've read the official solution and understand it but this is what I came up with on my own first.
Question:
Learn about operator overloading and how the different conventions for operations like ==, <, work in Kotlin. Add the function compareTo to the class MyDate to make it comparable. After this, the code below date1 < date2 should start to compile.
Note that when you override a member in Kotlin, the override modifier is mandatory.
My Answer:
import java.time.Duration
import java.time.LocalDate
data class MyDate(val year: Int, val month: Int, val dayOfMonth: Int) : Comparable<MyDate> {
override fun compareTo(other: MyDate): Int {
val dateA = LocalDate.of(this.year, this.month, this.dayOfMonth)
val dateB = LocalDate.of(other.year, other.month, other.dayOfMonth)
return Duration.between(dateA, dateB).toDays().toInt()
}
}
fun test(date1: MyDate, date2: MyDate) {
// this code should compile:
println(date1 < date2)
}
I went at this thinking I would work out the difference between the two in days and just return it. but the error I get is "Unsupported unit: Seconds" What does this mean in this context. I believe I'm returning the correct type from compareTo as an int. What am I missing here?
This is the official solution for reference
data class MyDate(val year: Int, val month: Int, val dayOfMonth: Int) : Comparable<MyDate> {
override fun compareTo(other: MyDate) = when {
year != other.year -> year - other.year
month != other.month -> month - other.month
else -> dayOfMonth - other.dayOfMonth
}
}
fun test(date1: MyDate, date2: MyDate) {
// this code should compile:
println(date1 < date2)
}
Different approach but I would expect the tests to pass both ways
CodePudding user response:
Duration
is time based, and works with Temporal
s that supports seconds. From between
:
The specified temporal objects must support the SECONDS unit. For full accuracy, either the NANOS unit or the NANO_OF_SECOND field should be supported.
LocalDate
does not support seconds. You should instead use Period.between
, or ChronoUnit.DAYS.between
.
Another mistake is that you are comparing the dates in the reverse order of the official solution. ChronoUnit.DAYS.between(dateA, dateB).toInt()
would give a positive number if dateA
(this
) is before dateB
(the parameter). If you look at the official solution, compareTo
returns a positive number if this
is after the parameter.
Therefore, you should do:
override fun compareTo(other: MyDate): Int {
val dateA = LocalDate.of(this.year, this.month, this.dayOfMonth)
val dateB = LocalDate.of(other.year, other.month, other.dayOfMonth)
// note the switched order
return ChronoUnit.DAYS.between(dateB, dateA).toInt()
}