This discussion is archived
10 Replies Latest reply: Sep 2, 2010 6:27 AM by 807580 RSS

Comparing Dates, What am I not seeing?

807580 Newbie
Currently Being Moderated
I have 3 dates and I want to sort them using a comparator.
Pls try below and you can see that they don't get sorted properly.
If I remove the times it works.
What am I doing wrong here?


import java.util.*;
import java.text.*;

public class DateTest
{
ArrayList<String> al = new ArrayList<String>();

public void fillList()
{
al.add("2010 08 30 12 55 43");

al.add("2010 8 31 12 54 26");
al.add("2010 09 01 12 53 10");
}
public ArrayList<String> sortMe()
{
Collections.sort(al, new Sorting());
return al;
}
public void printList(ArrayList<String> alist)
{
for (int i=0; i < alist.size(); i++)
System.out.println(alist.get(i));
}
public static void main(String [] args)
{
DateTest dt = new DateTest();
dt.fillList();
ArrayList<String> sorted = dt.sortMe();
dt.printList(sorted);
}
}
class Sorting implements Comparator
{
Calendar gc0 = Calendar.getInstance();;
Calendar gc1 = Calendar.getInstance();;

public int compare(Object arg0, Object arg1)
{
String[] d0 = ((String)arg0).split(" ");
String[] d1 = ((String)arg1).split(" ");

try
{
int yr0 = Integer.parseInt(d0[0]);
int mo0 = Integer.parseInt(d0[1]);
int day0 = Integer.parseInt(d0[2]);
int yr1 = Integer.parseInt(d1[0]);
int mo1 = Integer.parseInt(d1[1]);
int day1 = Integer.parseInt(d1[2]);
int hr0 = Integer.parseInt(d0[3]);
int hr1 = Integer.parseInt(d1[3]);
int min0 = Integer.parseInt(d0[4]);
          int min1 = Integer.parseInt(d1[4]);
int sec0 = Integer.parseInt(d0[5]);
          int sec1 = Integer.parseInt(d1[5]);


gc0.set(yr0,mo0,day0, hr0, min0, sec0);
gc1.set(yr1,mo1,day1,hr1, min1, sec1);
System.out.println("cal 0 is "+yr0+" month0 ia "+mo0+" day0 is "+day0+" cal0 is "+gc0.getTimeInMillis());
System.out.println("cal 1 is "+yr1+" month1 ia "+mo1+" day1 is "+day1+" cal1 is "+gc1.getTimeInMillis());

if(gc0.after(gc1))
{
return -1;
}
else if(gc0.before(gc1))
{
return 1;
}
else
{
return 0;
}
}
catch(NumberFormatException n)
{
System.out.println("failed on inputs ");
}
return 0;

}
}
  • 1. Re: Comparing Dates, What am I not seeing?
    796262 Newbie
    Currently Being Moderated
    When posting code, make sure you use the CODE tags to preserve formatting.
  • 2. Re: Comparing Dates, What am I not seeing?
    807580 Newbie
    Currently Being Moderated
    Rather than use a Calendar you should use SimpleDateFormat.parse() to parse the String into java.util.Date objects inside your comparator.
  • 3. Re: Comparing Dates, What am I not seeing?
    807580 Newbie
    Currently Being Moderated
    I will try that. But is there anything wrong with the way it is currently implemented?
    Seems like it follows the API ;-(
  • 4. Re: Comparing Dates, What am I not seeing?
    807580 Newbie
    Currently Being Moderated
    Yes, that worked. But I am still confused as to why I cannot compare
    Calendars that way.
  • 5. Re: Comparing Dates, What am I not seeing?
    807580 Newbie
    Currently Being Moderated
    SkirtedOne wrote:
    I will try that. But is there anything wrong with the way it is currently implemented?
    Since it does not work according to your expectation then obviously it has a bug. I'm not going to go though all that convoluted comparator code when I know it can all be replaced by just one SimpleDateFormat instance and one other active line of code.
    Seems like it follows the API ;-(
  • 6. Re: Comparing Dates, What am I not seeing?
    807580 Newbie
    Currently Being Moderated
    SkirtedOne wrote:
    Yes, that worked. But I am still confused as to why I cannot compare
    Calendars that way.
    Even though you were given a good solution, I was still wondering why your comparison wasn't working and I might have figured this out.

    I think your problem is when you call :
    gc0.set(yr0,mo0,day0, hr0, min0, sec0);
    with the values 2010 8 31.

    When the set method is called for the field Calendar.MONTH, the Calendar javadoc explains that "The first month of the year is JANUARY which is 0". This implies that the date you are setting is in fact 2010 / 09 / 31 (September 31...).
    As the Javadoc says :
    "+the calendar's time value in milliseconds is not recomputed until the next call to get(), getTime(), getTimeInMillis(), add(), or roll() is made+.".
    Thus, when you call gc0.getTimeInMillis() within your System.out statement, the date you will actually get is October 1, 2010, 12:54:26.
    This date is, of course, greater than October 1, 2010, 12:53:10.

    By the way, an example is also given in the javadoc :
    "+Example: Consider a GregorianCalendar originally set to August 31, 1999. Calling set(Calendar.MONTH, Calendar.SEPTEMBER) sets the date to September 31, 1999. This is a temporary internal representation that resolves to October 1, 1999 if getTime()is then called+"

    To summarize : when you think you are comparing 2010 / 09 / 01 12:53:10 and 2010 / 8 / 31 12:54:26, it is not the case. Instead, you are comparing 2010 / 10 / 01 12:53:10 and 2010 / 10 / 31 12:54:26.

    I think this is why you don't get the results you are expecting.
    But of course, I agree with the other posts stating that you should not proceed this way to manipulate the dates.
  • 7. Re: Comparing Dates, What am I not seeing?
    807580 Newbie
    Currently Being Moderated
    SkirtedOne wrote:
    Yes, that worked. But I am still confused as to why I cannot compare
    Calendars that way.
    if gc0 is after gc1 shouldn't it return 1 and if gc0 is before gc1 shouldn't it return -1. I think you have that backwards. Also Calendar implements comparable so you can simple go
    return gc0.compareTo(gc1)
    and not mess around with after() and before()
  • 8. Re: Comparing Dates, What am I not seeing?
    807580 Newbie
    Currently Being Moderated
    Alex, thanks for taking the time to look into this.

    Yes, I noticed both of those things, and in fact that's why I called getTimeInMillis() in the print statement.
    Wouldn't this update the calendar before the comparison?

    As for the peculiar 0-based months thingy, I had forgotten about it. Do you mean that becuz
    it is really 10 instead of 9, that 8/31 becomes 9/31 which resolves to 10/1? That makes sense.

    I just tried it by reducing the months by 1 and it worked.

    Regards.
  • 9. Re: Comparing Dates, What am I not seeing?
    807580 Newbie
    Currently Being Moderated
    SkirtedOne wrote:
    Alex, thanks for taking the time to look into this.

    Yes, I noticed both of those things, and in fact that's why I called getTimeInMillis() in the print statement.
    Wouldn't this update the calendar before the comparison?

    As for the peculiar 0-based months thingy, I had forgotten about it. Do you mean that becuz
    it is really 10 instead of 9, that 8/31 becomes 9/31 which resolves to 10/1? That makes sense.

    I just tried it by reducing the months by 1 and it worked.

    Regards.
    I thought I had explained this in my previous post. I quoted some examples I found in the Javadoc to be as precise as possible (one of them describes exactly the problem you faced).
    But if you still have some doubts, I encourage you to read http://download.oracle.com/javase/6/docs/api/java/util/Calendar.html
    and particularly the parts "Leniency" and "Field manipulation".

    Regards.
  • 10. Re: Comparing Dates, What am I not seeing?
    807580 Newbie
    Currently Being Moderated
    it is really 10 instead of 9, that 8/31 becomes 9/31 which resolves to 10/1? That makes sense.
    I just tried it by reducing the months by 1 and it worked.
    I made the change that you suggested and mentioned that it worked.