Hot questions for Using Joda-Time in sorting

Question:

How to sort LocalDateTime objects?

I tried the following:

Comparator<Data> comparator = new Comparator<Data>() {
    @Override
    public int compare(final data o1, final data o2) {
        if (o1.getDate()== null || o2.getDate() == null)
            return 0;
        return o1.getDate().compareTo(o2.getDate());
    }
};

Collections.sort(comments, comparator);

After testing I think it sorts according to the date, but is the time part (HH:MM:SS) ignored?


Answer:

Both JodaTime and JDK 8 LocalDateTime classes implement the Comparable interface, so you can sort them using their natural order. Just do

Collections.sort(data);

Question:

I have a timestamp string like this:

2016-01-14T22:43:55Z
2016-01-15T00:04:50Z
2016-01-15T00:44:59+08:30
2016-01-15T01:25:35-05:00
2016-01-15T01:44:31+08:30
2016-01-15T02:22:45-05:00
2016-01-15T02:54:18-05:00
2016-01-15T03:53:26-05:00
2016-01-15T04:32:24-08:00
2016-01-15T06:31:32Z
2016-01-15T07:06:07-05:00

I want to sort them so that I can get what is starting range and ending range from above timestamp. I am doing like below:

List<String> timestamp = new ArrayList<>();
// adding above string timestamp into this list
// now sort it
Collections.sort(timestamp);

This will give me start and end range from the above list of timestamp. Is this the right way to do it or there is any better way?

timestamp.get(0); // start range
timestamp.get(timestamp.size() - 1); // end range

Update

So I should do something like below:

List<OffsetDateTime> timestamp = new ArrayList<>();
timestamp.add(OffsetDateTime.parse( "2016-01-15T00:44:59+08:30" ));
// add other timestamp string like above and then sort it
Collections.sort(timestamp);

timestamp.get(0); // start range
timestamp.get(timestamp.size() - 1); // end range

Answer:

OffsetDateTime

Parse those ISO 8601 strings into java.time.OffsetDateTime objects.

OffsetDateTime.parse( "2016-01-15T00:44:59+08:30" )

Add those date-time objects to a Collection and sort. You probably want a List such as ArrayList or a SortedSet.

The java.time classes implement the compareTo method, to fulfill their contract as a Comparable. So these objects know how to sort.

Like this:

List<OffsetDateTime> odts = new ArrayList<>();

OffsetDateTime odt = OffsetDateTime.parse( "2016-01-15T00:44:59+08:30" ) ;
odts.add( odt );
… // Parse remaining ISO 8601 strings, adding each new OffsetDateTime object to collection.

Collections.sort( odts );

Question:

I have a List of dates in dd.MM.YYYY HH:mm format stored as a string When I try to sort these dates I get all the values sorted properly except for the 00 hours and 12 hours values

The array comes in a 15 minute interval so after sorting i get something like

00:15, 12:15, 00:30, 12:30, 00:45, 12:45, 1:00, 1:15, 1:30....

Below is the code for the sorting

Collections.sort(dates, new Comparator<String>() {
            DateFormat f = new SimpleDateFormat("dd.MM.yyyy hh:mm");
            @Override
            public int compare(String o1, String o2) {
                try {
                    return f.parse(o1).compareTo(f.parse(o2));
                } catch (ParseException e) {
                    throw new IllegalArgumentException(e);
                }
            }
        });

Please help me out here how do i go ahead with this


Answer:

In your SimpleDateFormat, use HH for hours instead of hh:

DateFormat f = new SimpleDateFormat("dd.MM.yyyy HH:mm");

As mentioned in the documentation:

H   Hour in day (0-23)
h   Hour in am/pm (1-12)

Question:

Below code converts a String date to a DateTime obj :

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormatter;

public class SortByDate
{
    // Date format is (mm/dd/yyyy)
    private void testSort()
    {

        List<Obj> l = new ArrayList<Obj>();

        Obj o =new Obj();
        o.date = "1/5/2015 1:37:00";
        l.add(o);
        o = new Obj();
        o.date = "1/5/2015 01:38:00";
        l.add(o);
        o = new Obj();
        o.date = "1/5/2015 01:36:00";
        l.add(o);
        o = new Obj();
        o.date = "1/5/2015";
        l.add(o);


        DateTimeFormatter dtf = org.joda.time.format.DateTimeFormat.forPattern("MM/dd/yyyy HH:mm:ss");

        List<DateTime> dtl = new ArrayList<DateTime>();
        for(Obj ob : l){
             dtl.add(dtf.parseDateTime(ob.date));
        }

        Collections.sort(dtl);

        for(DateTime d : dtl){
            System.out.println(d);
        }
    }

    public static void main(String args[])
    {
        new SortByDate().testSort();
    }

    private class Obj
    {
        public String date;
    }

}

But I receive exception :

Exception in thread "main" java.lang.IllegalArgumentException: Invalid format: "1/5/2015" is too short
    at org.joda.time.format.DateTimeFormatter.parseDateTime(DateTimeFormatter.java:899)

To sort the date descending and cater for dates that do not have time set I plan to append "23:23:59" to Strings that have incorrect format, so "1/5/2015" becomes "1/5/2015 23:23:59"

Is there a more idiomatic approach for handling this scenario or alternative method?


Answer:

"MM/dd/yyyy HH:mm:ss" is the format that your program expects. Passing a string with another format "MM/dd/yyyy" is properly handled as an error.

You could use regular expressions check and different dateformatter

 if(ob.date.matches(REG_EX_FULLDATE)){
      // use dateFormatter1
  }
 else if(ob.date.matches(REG_EX_SHORTDATE)){
     // use dateFormatter2
 } else {
       throw new RuntimeException();
 }