Sort date and time values
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
Akeshwar Jha
Updated on August 29, 2022Comments
-
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.