Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Compare dates ignoring milliseconds?

Is there a way to compare two calendar objects, but ignore milliseconds?

I have written a test case that compared two calendar objects, but there is a problem. Although all of the day, month, minutes and hours match, the milliseconds doesn't matches. I get the expected date before getting the real date:

/**
 * @return
 */
private Calendar getExpectedOneMonthDateFromCurrentDate() {
    Calendar expectedOneMonth = Calendar.getInstance();
    expectedOneMonth.add(Calendar.MONTH, -1);
    return expectedOneMonth;
}

assertEquals(getExpectedOneMonthDateFromCurrentDate(),
             DateRange.LAST_ONE_MONTH.getToDate());
like image 688
Jonathan Avatar asked Aug 07 '12 10:08

Jonathan


People also ask

How do you compare only dates?

For comparing the two dates, we have used the compareTo() method. If both dates are equal it prints Both dates are equal. If date1 is greater than date2, it prints Date 1 comes after Date 2. If date1 is smaller than date2, it prints Date 1 comes after Date 2.

Can you compare Datetimes?

The DateTime. Compare() method in C# is used for comparison of two DateTime instances. It returns an integer value, <0 − If date1 is earlier than date2.

How can I compare two dates in C#?

Compare() Method in C# This method is used to compare two instances of DateTime and returns an integer that indicates whether the first instance is earlier than, the same as, or later than the second instance. Syntax: public static int Compare (DateTime t1, DateTime t2);


6 Answers

Remove milliseconds from your calendar

cal.set(Calendar.MILLISECOND, 0);
like image 77
mishadoff Avatar answered Oct 13 '22 07:10

mishadoff


You need to use

cal.set(Calendar.MILLISECOND, 0);

and possibly as well

cal.set(Calendar.SECOND, 0);

if you just need the minutes to match.

like image 20
Peter Lawrey Avatar answered Oct 13 '22 07:10

Peter Lawrey


The solution of setting the milliseconds to 0 has an issue: if the dates are 12:14:29.999 and 12:14:30.003, you will set the dates to 12:14:29 and 12:14:30 respectively and will detect a difference where you don't want to.

I have thought about a Comparator:

private static class SecondsComparator implements Comparator<Calendar>
{
    public int compare(Calendar o1, Calendar o2)
    {
        final long difference = o1.getTimeInMillis() - o2.getTimeInMillis();
        if (difference > -1000 && difference < 1000)
            return 0;
        else
            return difference < 0 ? 1 : -1;
    }
}

public static void main(String args[])
{
    Calendar c1 = Calendar.getInstance();
    Utils.waitMilliseconds(100);
    Calendar c2 = Calendar.getInstance();
    // will return 0 
    System.out.println(new SecondsComparator().compare(c1,c2));
}

However, it no a good solution neither, as this Comparator breaks the following rule:

The implementer must ensure that x.compareTo(y)==0 implies that sgn(x.compareTo(z)) == sgn(y.compareTo(z)), for all z.

What leads to (x=y and y=z) => x=z.

So I don't see any solution... But indeed, if you define some different dates, they are different, aren't they?

like image 23
Olivier Faucheux Avatar answered Oct 13 '22 07:10

Olivier Faucheux


IMHO the easiest way is to use truncate() from Apache Commons DateUtils (Apache Commons DateUtils) to remove the milliseconds and compare the resulting dates.

like image 22
Manuel Avatar answered Oct 13 '22 07:10

Manuel


If you are on Java 8, you can use the Java Time API, specifically Calendar::toInstant(), followed by Instant::truncatedTo(). Specify the granularity of truncation using ChronoUnit enum.

myCalendar.toInstant().truncatedTo( ChronoUnit.SECONDS )  // Lop off any fractional second.

Example.

    Calendar oneMonthIsh = Calendar.getInstance();
    oneMonthIsh.add(Calendar.MONTH, -1);
    oneMonthIsh.add(Calendar.MINUTE, 1);

    assertNotEquals(oneMonthIsh.toInstant(), getExpectedOneMonthDateFromCurrentDate());
    assertEquals(oneMonthIsh.toInstant().truncatedTo(ChronoUnit.DAYS),getExpectedOneMonthDateFromCurrentDate().toInstant()
    .truncatedTo(ChronoUnit.DAYS));
like image 29
Dan Watt Avatar answered Oct 13 '22 07:10

Dan Watt


One option is to call Calendar.set(Calendar.MILLISECOND, 0) to clear the milliseconds. Another is call getTimeInMillis() to get the time in milliseconds for both calendars. You could then divide these by 1000 before comparing to remove the milliseconds.

like image 38
Simon Avatar answered Oct 13 '22 06:10

Simon