12

I'm trying to create a Kotlin REST API, which retrieves values from a PostgreSQL database. Now the values in these results are f.e. "14-10-2016 | 15:48" and "01-08-2015 | 09:29" So the syntax basically is dd-MM-yyyy | hh:mm

Now what I'm trying to do is create a function that will order them by date placed. (Assume these strings are in an array)

var list = listOf("14-10-2016 | 15:48",
                  "01-08-2015 | 09:29",
                  "15-11-2016 | 19:43")

What would be the cleanest (and most functional) way of sorting these? (so f.e. is there a way where I don't have to take substrings of the day, month, etc. cast them to an Int, compare them in a nested loop and write the results to a different array? (that's the only way I could think of).

4 Answers 4

13

More than one approach can be used. It depends on how you process after you get the sorted result.

Points to note:

  • java.time.LocalDateTime has already implemented java.lang.Comparable<T> Interface. We can use the kotlin stdlib List.sortBy to sort the List<LocalDateTime> directly.

Ref:

// https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/sorted-by.html
fun <T, R : Comparable<R>> Iterable<T>.sortedBy(
    selector: (T) -> R?
): List<T>

The easiest way is to transform the String -> java.time.LocalDateTime and use the List.sortBy directly.

The whole implementation could be like this:

 import java.time.LocalDateTime
 import java.time.format.DateTimeFormatter

 ...


// Create a convert function, String -> LocalDateTime
val dateTimeStrToLocalDateTime: (String) -> LocalDateTime = {
    LocalDateTime.parse(it, DateTimeFormatter.ofPattern("dd-MM-yyyy | HH:mm"))
}

val list = listOf("14-10-2016 | 15:48",
        "01-08-2015 | 09:29",
        "15-11-2016 | 19:43")

// You will get List<LocalDateTime> sorted in ascending order
list.map(dateTimeStrToLocalDateTime).sorted()

// You will get List<LocalDateTime> sorted in descending order
list.map(dateTimeStrToLocalDateTime).sortedDescending()

// You will get List<String> which is sorted in ascending order
list.sortedBy(dateTimeStrToLocalDateTime)

// You will get List<String> which is sorted in descending order
list.sortedByDescending(dateTimeStrToLocalDateTime)

If you want to use org.joda.time.DateTime, you can just make a tiny change on the convert function.

A friendly reminder, always pick val as your first choice in Kotlin :).

Sign up to request clarification or add additional context in comments.

2 Comments

@elect Immutable objects are always easier to trace and can be used in mutli-threaded environment without any worries. Most of the time you won't need var in Kotlin if you are familiar with functional approach. But var is more memory efficient, use it wisely to take the only benefit.
Call requires API level 26 though. Any backward compatible solutions?
4

Another alternative to the excellent Saravana answer (for minimalist and compact freaks like me..) is:

val cmp = compareBy<String> { LocalDateTime.parse(it, DateTimeFormatter.ofPattern("dd-MM-yyyy | HH:mm")) }

list.sortedWith(cmp).forEach(::println)

01-08-2015 | 09:29
14-10-2016 | 15:48
15-11-2016 | 19:43

Ps: it is the default variable for single inputs

1 Comment

instead of using map to print, maybe use list.sortedWith(cmp).forEach(::println)
0

You could use DateTimeFormatter to parse and then compare with LocalDateTime

    List<String> dates = Arrays.asList("14-10-2016 | 15:48", "01-08-2015 | 09:29", "15-11-2016 | 19:43");
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd-MM-yyyy | HH:mm");
    List<LocalDateTime> dateTimes = dates.stream().map(date -> LocalDateTime.parse(date, formatter)).sorted().collect(Collectors.toList());
    System.out.println(dateTimes);

Output

[2015-08-01T09:29, 2016-10-14T15:48, 2016-11-15T19:43]

Update

You could simply convert to LocalDateTime in Comparator alone

List<String> sortedDates = dates.stream().sorted(Comparator.comparing(date -> LocalDateTime.parse(date, formatter))).collect(Collectors.toList());

output

[01-08-2015 | 09:29, 14-10-2016 | 15:48, 15-11-2016 | 19:43]

2 Comments

Not sure Kotlin is compatible with Java 8, but anyway, I guess the OP was looking for a solution written in Kotlin.
@Egor sorry, I know Java only but the logic would be similar to the answer I posted
0

If you are using a custom object dates list sorted as below.

println("--- ASC ---")  
dates.sortBy { it.year }
println("--- DESC ---")
dates.sortByDescending { it.year }

You can use sortByDescending {it.field} for descending order.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.