Working with java.time in Kotlin: love, pain, suffering

A micropost about how you can fool yourself when using the Kotlin feature: the ability to work with comparison operators like Comparable.





Those who use Kotlin could not help but appreciate the operator overloading (well, more precisely, how it is done), although, for example, I lived in Java and it was fine without it, but this is not about this language feature, but about the one based on it: Comparison Operations. This is when comparison signs can be applied to classes that implement Comparable, which is sugar, but very nice.





And so, let's practice on synthetics: we have some kind of time period, i.e. start and end date and time and we need to check the fact of intersection of time intervals.





In Java (I write as briefly as possible and without accepted norms, just convey the idea):





class TimeIterval {
  LocalDateTime from;
  LocalDateTime to;
}
class TimeIntervalUtil {
  public boolean areOverlapped(TimeInterval first, TimeInterval second) {
            return (first.from.isEqual(second.to) || first.from.isBefore(second.to)) &&
                (first.to.isEqual(second.from) || first.to.isAfter(second.from));
  }
}
      
      



those. nothing complicated, but just in case I will explain the code (I have to explain to myself such a code when I meet it): the intersection of two intervals is possible only if the start date of one came earlier or at the same time in relation to the end date of the second and at the same time end date of the first interval comes later or at the beginning of the second.





Now the same thing but on Kotlin with its sugar, but without the rangers:





data class TimeInterval(val from: LocalDateTime, val to: LocalDateTime)
fun areOverlapped(first: TimeInterval, second: TimeInterval): Boolean = 
  first.from <= second.to && first.to >= second.from
      
      



Well, I think without comments where you can see better, what is more pleasant to use and faster to understand. Satisfied, we go to Kotlin and start working by analogy with OffsetDateTime.





, OffsetDateTime. Comparable, java.time. LocalDateTime. Java , .





compareTo, Kotlin , LocalDateTime ( , , ), .





OffsetDateTime , , compareTo , .. 2021-04-25 10:00+0 2021-04-25 11:00+1 . :





val inUtc = OffsetDateTime.of(LocalDateTime.of(2021, 4, 25, 10, 0), ZoneOffset.UTC)
val inUtc1 = OffsetDateTime.of(LocalDateTime.of(2021, 4, 25, 11, 0), ZoneOffset.ofTotalSeconds(60*60))
println(inUtc1>=inUtc && inUtc1 <= inUtc)
println(inUtc.isEqual(inUtc1))
      
      



Of course, it is correct to use not isEqual here, but - == and generally separate isEqual + isBefore + isAfter and Comparable + equal, but unfortunately I sometimes tend not to notice the difference, especially when I have a convenient approach with comparison operators.





This is how you can easily and naturally create an unobvious bug in the case of thoughtless use of comparison operators in Kottlein with the java.time api.








All Articles