Hi! I have a question! class : ```data class MyD...
# getting-started
s
Hi! I have a question! class :
Copy code
data class MyDate(val year: Int, val month: Int, val dayOfMonth: Int) : Comparable<MyDate> {}
function:
Copy code
fun test(date1: MyDate, date2: MyDate) {
    // this code should compile:
    println(date1 < date2)
}
Problem: I need to write a method for comparing MyDate objects I write a solution, it works ok
Copy code
override fun compareTo(other: MyDate): Int {
    val yearDiff = year - other.year
    val monthDiff = month - other.month
    val dayDiff = dayOfMonth - other.dayOfMonth

    if (yearDiff == 0) {
        if (monthDiff == 0) {
            if (dayDiff == 0) {
                return 0
            }
        } else return monthDiff
    } else return yearDiff

    return 0;
}
and now “good” solution:
Copy code
override fun compareTo(other: MyDate) = when {
    year != other.year -> year - other.year
    month != other.month -> month - other.month
    else -> dayOfMonth - other.dayOfMonth
}
i am not understand how works “good” solution? can you help me? what does mean
Copy code
year != other.year -> year - other.year
c
`when`is similar to a switch statement - the first part (before the ->) is the criteria to match (year != other.year); the second part (after the ->) is what to do when the criteria is satisfied.
👌🏻 1
e
BTW, you would be better off writing it as
Copy code
override fun compareTo(other: MyDate): Int =
    compareValuesBy(this, other, { it.year }, { it.month }, { it.dayOfMonth })
which is not only simpler, but also avoids overflow problems with
-
🆒 2
e.g.
Copy code
val a = MyDate(0, 0, 0)
val b = MyDate(Int.MIN_VALUE, 0, 0)
you would expect that
a > b
, but due to
-
, your comparison will actually produce
a < b
m
About the “good” solution it works because it’s exploiting the when (analogous to Java switch, or to an if/else if/… series) in cascade: if the years are different we just need to compare them, here by subtracting, otherwise we compare the months if different, or we end up comparing the days.
e
-
isn't a good solution either way, IMO. if you don't want to use the stdlib functions, then at least
Copy code
when {
    year < other.year -> -1
    year > other.year -> 1
    month < other.month -> -1
    month > other.month -> 1
    dayOfMonth < other.dayOfMonth -> -1
    dayOfMonth > other.dayOfMonth -> 1
    else -> 0
}
avoids overflow issues
n
BTW: your "ok" solution produces the wrong result if
year
and
month
are equal but
dayOfMonth
is not
1
s
“ok” solution worl correctly
best solution is
Copy code
compareValuesBy(this, other, { it.year }, { it.month }, { it.dayOfMonth })
imho
thanks a lot for all
n
I agree that
compareValuesBy
is the best solution. but your "ok" is not ok: it will return
0
instead of
5
for
MyDate(2022, 1, 10).compareTo(MyDate(2022, 1, 5))
. You have to use
Copy code
if (yearDiff == 0) {
        if (monthDiff == 0) {
            return dayDiff
        } else return monthDiff
    } else return yearDiff
👌🏻 1
s
yes, you are right! i fix code for this
Copy code
override fun compareTo(other: MyDate): Int {
    val yearDiff = year - other.year
    val monthDiff = month - other.month
    val dayDiff = dayOfMonth - other.dayOfMonth

    if (yearDiff == 0) {
        if (monthDiff == 0) {
            if (dayDiff == 0) {
                return 0
            } else return dayDiff
        } else return monthDiff
    } else return yearDiff

}
and now correct
I am added else return DayDiff
e
just don't use
-
. if you really wanted to keep that structure for some reason,
Copy code
val yearComparison = compareValues(year, other.year)
val monthComparison = compareValues(month, other.month)
val dayComparison = compareValues(day, other.day)
return when {
    yearComparison != 0 -> yearComparison
    monthComparison != 0 -> monthComparison
    else -> dayComparison
}
👍🏻 1