Sort date and time values

12,663

Solution 1

I have a string array. Each element is of this format: 2015-08-27T22:24:31.903. Is there a default method available to sort this format?

Yes. Since the ISO string has date fields in descending order of magnitude, and fields are fixed-width, you can simple sort the strings directly using Arrays.sort(Object[] a): Sorts the specified array of objects into ascending order, according to the natural ordering of its elements.

Is there a direct parser for this format available?

Yes. LocalDateTime.parse(CharSequence text): Obtains an instance of LocalDateTime from a text string such as 2007-12-03T10:15:30.

Solution 2

I take it those are strings. If you don't want to do the obvious (convert them to LocalDateTime¹ and compare the result), you can just compare them as strings, that particular date-time format (a nearly-full ISO-8601 timestamp, just missing a timezone indicator) works correctly when you use string comparison.

Gratuitous example (live copy):

import java.util.*;

class Example
{
    public static void main (String[] args)
    {
        String[] strings = {
            "2002-10-24T13:51:25.417",
            "2001-03-25T23:41:24.234",
            "2008-10-05T04:41:56.004",
            "2013-04-10T22:14:06.852",
            "2005-08-24T05:05:01.080",
            "2015-11-20T17:32:27.303",
            "2003-07-16T06:32:07.703",
            "2005-03-20T08:28:18.440",
            "2009-04-17T13:20:09.499",
            "2002-11-04T06:39:55.287"
        };
        Arrays.sort(strings);
        for (String s : strings) {
            System.out.println(s);
        }
    }
}

Output:

2001-03-25T23:41:24.234
2002-10-24T13:51:25.417
2002-11-04T06:39:55.287
2003-07-16T06:32:07.703
2005-03-20T08:28:18.440
2005-08-24T05:05:01.080
2008-10-05T04:41:56.004
2009-04-17T13:20:09.499
2013-04-10T22:14:06.852
2015-11-20T17:32:27.303

You can, of course, provide a Comparator if you need a different ordering (such as reverse order).


¹ or Instant, if these are actually UTC date/times, but you'd need to add a Z to the end of the strings before parsing.

Solution 3

Using modern Java

The Answer by Andreas is correct. Here is a variation using newer features added to later versions of Java.

Make some example data using List.of. The resulting list is nonmodifiable. So feed the nonmodifiable list to the constructor of ArrayList to get a modifiable list we can sort.

List < String > strings = new ArrayList <>(
        List.of(
                "2015-08-27T22:24:31.903" ,
                "2018-08-27T22:24:31.903" ,
                "2016-08-27T22:24:31.903" ,
                "2017-08-27T22:24:31.903"
        )
);

Sort as text

As noted in that other Answer, your strings are in standard ISO 8601 format. That particular format is designed to be chronological when sorted alphabetically. So, if this task is your only goal for this data, then you need not parse as date-time object. Just sort as text, as String objects.

Rather than using the Collections utility class, the List interface has gained the sort method. That method demands a Comparator. Rather than implement that interface, we can call Comparator.naturalOrder() to produce an instance.

strings.sort( Comparator.naturalOrder() );

Dump to console.

System.out.println( "strings = " + strings );

See this code run live at IdeOne.com.

strings = [2015-08-27T22:24:31.903, 2016-08-27T22:24:31.903, 2017-08-27T22:24:31.903, 2018-08-27T22:24:31.903]

Sort as date-time objects

If you will be further work with this input, then parse as date-time objects.

The modern approach uses java.time classes.

We can simplify our example data, as we can work directly with a nonmodifiable List produced by List.of.

List < String > strings =
        List.of(
                "2015-08-27T22:24:31.903" ,
                "2018-08-27T22:24:31.903" ,
                "2016-08-27T22:24:31.903" ,
                "2017-08-27T22:24:31.903"
        );

Make an empty List of LocalDateTime objects.

List < LocalDateTime > ldts = new ArrayList <>( strings.size() );

Populate that list by parsing our input strings one at a time, producing a LocalDateTime object. Add that object to our list.

Notice that java.time classes use ISO 8601 formats by default. So no need to specify a formatting pattern.

for ( String string : strings )
{
    ldts.add( LocalDateTime.parse( string ) );  // Parsing text in ISO 8601 format needs no formatting pattern to be specified.
}

Sort, as we did above. Call List::sort, passing a Comparator.

ldts.sort( Comparator.naturalOrder() ) ;

See that code run live at IdeOne.com.

System.out.println( "ldts = " + ldts );

Streams

We can replace the for loop with a Stream, if we want to get fancy. We can do this work as a one-liner.

List < String > strings =
        List.of(
                "2015-08-27T22:24:31.903" ,
                "2018-08-27T22:24:31.903" ,
                "2016-08-27T22:24:31.903" ,
                "2017-08-27T22:24:31.903"
        );

List < LocalDateTime > ldts = 
    strings
    .stream()
    .map( s -> LocalDateTime.parse( s ) )
    .sorted()
    .collect( Collectors.toList() )
;

System.out.println( "ldts = " + ldts );

ldts = [2015-08-27T22:24:31.903, 2016-08-27T22:24:31.903, 2017-08-27T22:24:31.903, 2018-08-27T22:24:31.903]

Solution 4

1) Parse your strings using the appropriate SimpleDateFormat:

SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-ddTHH:mm:ss.SSS");
try {
    Date date = formatter.parse(dateInString);
} catch (ParseException e) {
    e.printStackTrace();
}

2) Store each date in a list. To do that firstly instantiate a new list...

ArrayList<Date> myDates = new ArrayList<Date>();

... after the parse command add each date to the list:

myDates.add(date);

3) Sort them using:

Collections.sort(myDates); // Ascending

or

Collections.sort(myDates, Collections.reverseOrder()); // Descending
Share:
12,663
Akeshwar Jha
Author by

Akeshwar Jha

Updated on August 29, 2022

Comments

  • Akeshwar Jha
    Akeshwar Jha over 1 year

    Putting simply, I have a string array of different dates and times. Each element is of this format:

    2015-08-27T22:24:31.903

    That is, YYYY-MM-DDTHH:MM:SS.MMM

    I'm sorting them. Is there a default method available to sort this format?

    What I'm doing now is splitting the string at T, converting the date and time to respective timestamps, adding them and then sorting the timestamp values. Is there a direct parser for this format available? A better solution is most-welcome.