jn1kk
jn1kk

Reputation: 5102

Dates Not Matching

I have a TreeMap of <DDate, Integer>.

DDate just contains month and year (month is 0 indexed, like in Java, JAN = 0);

My compare is not returning the right thing:

@Override
public int compareTo(DDDate o) {

    Calendar cal1 = Calendar.getInstance();
    cal1.setTimeZone(TimeZone.getTimeZone("UTC"));
    cal1.set(year, month, 1); // year is 2012, month is 1

    Calendar cal2 = Calendar.getInstance();
    cal2.setTimeZone(TimeZone.getTimeZone("UTC"));
    cal2.set(o.getYear(), o.getMonth(), 1); // year is 2012, month is 1


    Log.log("COMPARING: " + format.format(cal1.getTime())); // COMPARING: 20120101
    Log.log("COMPARING: " + format.format(cal2.getTime())); // COMPARING: 20120101

    Log.log((cal1.getTime().getTime())); // 1325413927678
    Log.log((cal2.getTime().getTime())); // 1325413927679

    Log.log("WILL RETURN: " + cal1.getTime().compareTo(cal2.getTime())); // WILL RETURN: -1

    return cal1.getTime().compareTo(cal2.getTime());

}

Why is there descrepancy in the two Calendar objects for the same Date? (1325413927678 vs 1325413927679)

Thank you!

FYI: this method works for a while, and then at a certain point, stops working.

P.S. - I understand this is overkill, I can have a simpler compareTo, but please humor me.

EDIT- FIX

Use JodaTime's LocalDate.

Or do this:

Calendar cal1 = Calendar.getInstance();
cal1.setTimeZone(TimeZone.getTimeZone("UTC"));
cal1.clear();
cal1.set(year, month, 1); // year is 2012, month is 1

Upvotes: 0

Views: 889

Answers (5)

Basil Bourque
Basil Bourque

Reputation: 338181

Jon Skeet's answer is correct.

Here is some example code showing how to use Joda-Time to do a comparison of dates. Much easier in Joda-Time rather than Java’s bundled Date/Calendar classes. Takes only 3 lines of code to both instantiate and compare.

// © 2013 Basil Bourque. This source code may be used freely forever by anyone taking full responsibility for doing so.

// Joda-Time - The popular alternative to Sun/Oracle's notoriously bad date, time, and calendar classes bundled with Java 7 and earlier.
// http://www.joda.org/joda-time/

// Joda-Time will become outmoded by the JSR 310 Date and Time API introduced in Java 8.
// JSR 310 was inspired by Joda-Time but is not directly based on it.
// http://jcp.org/en/jsr/detail?id=310

// By default, Joda-Time produces strings in the standard ISO 8601 format.
// https://en.wikipedia.org/wiki/ISO_8601

// New DateTime instance with default time zone. For specific zone, call "withZone()" method.
org.joda.time.DateTime dateTimeX = new org.joda.time.DateTime();
org.joda.time.DateTime dateTimeY = new org.joda.time.DateTime(2012, 1, 1, 0, 0); // First of January.

// To compare the date only while ignoring the time, set identical time component on both.
// Call withTimeAtStartOfDay() to set same time value.
Boolean isSameDate = dateTimeX.withTimeAtStartOfDay().isEqual(dateTimeY.withTimeAtStartOfDay());

Upvotes: 0

Inouz
Inouz

Reputation: 76

Try using the clear() method before setting the date:

final Calendar cal1 = Calendar.getInstance();
cal1.clear();
cal1.setTimeZone(TimeZone.getTimeZone("UTC"));
cal1.set(2012, 1, 1); // year is 2012, month is 1

final Calendar cal2 = Calendar.getInstance();
cal2.clear();
cal2.setTimeZone(TimeZone.getTimeZone("UTC"));
cal2.set(2012, 1, 1); // year is 2012, month is 1

cal1.getTime().compareTo(cal2.getTime()); // Returns 0

Upvotes: 0

thst
thst

Reputation: 4602

You should initialize the calendar properly to "no time" (0 ticks), this should fix the issue.

cal1.setTime(new Date(0));
cal1.set(year, month, 1);

Upvotes: 0

Quillion
Quillion

Reputation: 6476

Because you are making them at two different times.

Calendar cal1 = Calendar.getInstance(); // time now 
cal1.setTimeZone(TimeZone.getTimeZone("UTC")); // time ticking
cal1.set(year, month, 1); // year is 2012, month is 1 // time ticking

Calendar cal2 = Calendar.getInstance(); // time two ticks later

You have changed the day and month and year, however the hour minutes and seconds stayed and keep on moving and chaning.

As mentioned here
http://docs.oracle.com/javase/7/docs/api/java/util/Calendar.html#set(int, int, int, int, int)
The other field values are retained and you should use clear() to set them to zero. Additionally as Jon recomended I would say use Joda time it is much better.

Upvotes: 2

Jon Skeet
Jon Skeet

Reputation: 1499800

You're setting the year, month and day - but that doesn't change the time of day. The internal clock must have ticked between the two calls to Calendar.getInstance, so they have different "milliseconds since the Unix epoch" values.

Personally I'd recommend using Joda Time instead of java.util.Calendar and java.util.Date - that way you can represent what you're actually interested in, such as LocalDate.

Upvotes: 6

Related Questions