0

I have the following List of ZonedDateTime which is basically read from xml fields in Scala:

var timestamps =  List[ZonedDateTime]()
timestampNodes.foreach(node => timestamps = timestamps :+ ZonedDateTime.parse(node.text, DateTimeFormatter.ISO_OFFSET_DATE_TIME))

What is the best and fastest way to sort the timestamps List so that entries are sorted from oldest to newest?

Ganesha
  • 145
  • 1
  • 10
  • 3
    Can't you just do `val sortedTimestamps = timestamps.sorted`? – marstran Sep 16 '21 at 13:56
  • 2
    On Scala >= 2.13.0 yes. Otherwise https://stackoverflow.com/questions/38059191/how-make-implicit-ordered-on-java-time-localdate – Jasper-M Sep 16 '21 at 14:38
  • Due to some dependencies, I have to use 2.11.12. So .sorted is not working. So custom sorting will have to implemented. – Ganesha Sep 16 '21 at 15:17
  • 1
    Does this answer your question? [How make implicit Ordered on java.time.LocalDate](https://stackoverflow.com/questions/38059191/how-make-implicit-ordered-on-java-time-localdate) – Jasper-M Sep 16 '21 at 15:18

2 Answers2

0

.sortWith() should work.

import java.time.{ZonedDateTime => ZDT}

val sortedtimestamps: List[ZDT] =
  timestampNodes.map(node => ZDT.parse(node.text))
                .sortWith(_.isBefore(_))

Scala 2.11.12 tested via Scastie.

jwvh
  • 50,871
  • 7
  • 38
  • 64
  • I have a case where node.text is empty. So the above map throws exception. If I introduce a if within the map, then sortwith doesn't work because the type of map() changes from Seq[ZDT] to Seq[Any]. How can this be handled? – Ganesha Sep 17 '21 at 15:34
  • If by "empty" you mean `""` then you can either add a `.filter(_.text.nonEmpty)` before the `.map(...`, or you can change the `.map()` to `.collect{case node if node.text.nonEmpty => ...`. – jwvh Sep 17 '21 at 16:22
  • Thanks. I used this to fix the issue : .filter(_.text.trim.nonEmpty) – Ganesha Sep 18 '21 at 09:13
0

Implement Ordering for ZonedDateTime and you can use List.sorted:

import java.time._
import scala.math.Ordering.Implicits._

implicit val zonedDateTimeOrdering: Ordering[ZonedDateTime] =
    _ compareTo _

val base = ZonedDateTime.of(
    LocalDate.of(2021, 1, 1),
    LocalTime.MIDNIGHT,
    ZoneOffset.UTC
)

List(
    base.plusHours(1),
    base.plusHours(4),
    base.plusHours(2)
).sorted      // ==> a list with oldest first

Tested with Scala 2.13 but should work with Scala 2.12 and later.

Bonus

Add an import and you can compare ZonedDateTime variables with <, <=, >, etc.

import scala.math.Ordering.Implicits._

base <= base.plusMinutes(10) // ==> true
Erik van Oosten
  • 1,541
  • 14
  • 16