views:

1030

answers:

1

Ok, I'm officially stumped on this one. I have a GregorianCalendar object that I would like to determine if it is in the past, present, or future. So far, the Calendar#compareTo docs are confusing to me, in that I am getting erratic results. A simple test class will illustrate my problem:

import java.util.Calendar;
import java.util.GregorianCalendar;
public class MyCal
{

        public static void main( String[] args )
        {
                GregorianCalendar datePast = new GregorianCalendar();
                datePast.add(Calendar.MONTH, -6); // subtract 6 months
                GregorianCalendar datePresent = new GregorianCalendar();
                GregorianCalendar dateFuture = new GregorianCalendar();
                datePast.add(Calendar.MONTH, 6); // add 6 months

                System.out.println("compare datePresent to datePast: "+datePresent.compareTo(datePast));
                System.out.println("compare datePresent to datePresent: "+datePresent.compareTo(datePresent));
                System.out.println("compare datePresent to dateFuture: "+datePresent.compareTo(dateFuture));
        }
}

And the output:

compare datePresent to datePast: 1
compare datePresent to datePresent: 0
compare datePresent to dateFuture: 0

My understanding of compareTo is that the last line should be a -1. Can anyone tell me what I'm doing wrong?

+2  A: 

You've added 6 months to datePast, not dateFuture. Here's the working code:

import java.util.Calendar;
import java.util.GregorianCalendar;
public class MyCal
{

    public static void main( String[] args )
    {
        GregorianCalendar datePast = new GregorianCalendar();
        datePast.add(Calendar.MONTH, -6); // subtract 6 months
        GregorianCalendar datePresent = new GregorianCalendar();
        GregorianCalendar dateFuture = new GregorianCalendar();
        dateFuture.add(Calendar.MONTH, 6); // add 6 months

        System.out.println("compare datePresent to datePast: "+datePresent.compareTo(datePast));
        System.out.println("compare datePresent to datePresent: "+datePresent.compareTo(datePresent));
        System.out.println("compare datePresent to dateFuture: "+datePresent.compareTo(dateFuture));
    }
}

Your results would have been inconsistent because sometimes dateFuture would be later than datePresent, depending on when the internal clock "ticked".

In addition to all of this, I can't help but give my standard Java date and time advice: use Joda Time instead. It's not responsible for this particular problem, although the fact that many of the types are immutable would have helped. But in general it's a much better library.

Jon Skeet
Wow, I feel ridiculously stupid. Thanks Jon.
localshred
Did you know it's impossible for anybody to ask a question on SO about Java Date or Calendar without at least one person mentioning Joda Time? If there were a SO drinking game, this would be rule 1.
Paul Tomblin
so if I have a follow up question should I create a new question altogether or alter this one?
localshred
@Paul: I like to mention it in the comments before anyone else answers, just to see if they still recommend it. They still do (I've tried this twice).
Michael Myers
@localshred, unless it's very minor, make a new question.
Paul Tomblin
@Paul: It's almost always me, too :) I'm somewhat fanatical about it. Dates and times are *really* hard. Even using Joda there are tricky situations, e.g. finding midnight on a day midnight doesn't exist. (There's a getStartOfDay method which helps for that though... once you've realised the issue.)
Jon Skeet
Well, after investigating further, I apparently had the same issue with my object code (same as the test code above). Thanks guys for your quick responses, even to this minor issue (ie. stupidity). I was killing myself over this.
localshred