Mahmoud Saleh
Mahmoud Saleh

Reputation: 33605

Date before method returns false if both dates are equal

When comparing two dates with date before method, if the dates are similar, it returns false as follows:

the method date1.before(date2) always returns false in this case, which does not make sense to me (doesn't apply to my case in other words). I want to check if a date (day/month/year) equals today's date (day/month/year)?

Upvotes: 51

Views: 114626

Answers (9)

StanleyKh
StanleyKh

Reputation: 101

Assertj's isBeforeOrEqualTo is an option for tests.

Examle for Instant taken from the doc:

// assertions succeed
// theTwoTowers release date : 2002-12-18
assertThat(theTwoTowers.getReleaseDate()).assertIsAfterOrEqualTo(Instant.parse("2002-12-17T00:00:00.00Z"))
                                         .assertIsAfterOrEqualTo(Instant.parse("2002-12-18T00:00:00.00Z"));
// assertion fails
assertThat(theTwoTowers.getReleaseDate()).assertIsAfterOrEqualTo(Instant.parse("2002-12-19T00:00:00.00Z"));

Upvotes: 1

xlecoustillier
xlecoustillier

Reputation: 16351

As date1.equals(date2), it is normal that date1.before(date2) returns false. As will do date1.after(date2).

Both dates are the same, so one is not before the other.

From the javadoc :

true if and only if the instant of time represented by this Date object is strictly earlier than the instant represented by when; false otherwise.

Try something like:

if (date1.before(date2) || date1.equals(date2)) ...

The answers provided below suggest testing for the inverse, and they're right:

if (!date1.after(date2)) ...

Both tests are equivalent.

Upvotes: 102

Anonymous
Anonymous

Reputation: 86280

The answers from 2012 are correct and were generally good answers back then. Nowadays we surely prefer to use java.time, the modern Java date and time API, over the Date class implied in the question. Date is poorly designed and now long outdated.

The two recommended ways to obtain a “before or equal” comparison are:

  1. The natural and wordy one:

        OffsetDateTime dateTime1 = OffsetDateTime.of(2012, 12, 18, 0, 0, 0, 0, ZoneOffset.ofHours(2));
        OffsetDateTime dateTime2 = OffsetDateTime.of(2012, 12, 18, 0, 0, 0, 0, ZoneOffset.ofHours(2));
    
        if (dateTime1.isBefore(dateTime2) || dateTime1.isEqual(dateTime2)) {
            System.out.println("dateTime1 is before or equal to dateTime2");
        } else {
            System.out.println("dateTime1 is after dateTime2");
        }
    

    Output is:

    dateTime1 is before or equal to dateTime2

    As an aside OffsetDateTime.isEqual() compares points in time, instants, across UTC offsets and will return true of the two objects denote the same point in time. Also isBefore() works across different UTC offsets.

  2. The brief one where we reverse the condition:

        if (dateTime1.isAfter(dateTime2)) {
            System.out.println("dateTime1 is after dateTime2");
        } else {
            System.out.println("dateTime1 is before or equal to dateTime2");
        }
    

    Output is the same as before.

Depending on requirements you could easily find yourself preferring the Instant class over OffsetDateTime. The if condition will be the same.

No matter if using the old-fashioned Date or one of the modern classes before means strictly before. So to obtain before or equal we need to use one of the variants above.

Upvotes: 0

alvaro torrico
alvaro torrico

Reputation: 755

The real problem with your code maybe is that you are not taking into account the millis and the before function does

Two objects java.util.Date with a toString result: Sun Aug 28 00:00:00 CEST 2016 may have a different value when calling to getTime. For instance

Date d1;
Date d2;
d1.toString(); // = Sun Aug 28 00:00:00 CEST 2016
d2.toString(); // = Sun Aug 28 00:00:00 CEST 2016
d1.getTime(); // = 1472335200605
d2.getTime(); // = 1472335200000

Of course, these dates are not equals.

From javadoc:

"Returns:true if and only if the instant of time represented by this Date object is strictly earlier than the instant represented by when; false otherwise."

Upvotes: 3

zygimantus
zygimantus

Reputation: 3777

You can use this also:

boolean check = dateOne.before(dateTwo) || DateUtils.isSameDay(dateOne, dateTwo);

DateUtils is from org.apache.commons.lang.time package

Upvotes: 6

Rafael Moreira
Rafael Moreira

Reputation: 1769

you can use the inverse like it was proposed by bowmore: !date1.after(date2)

Or if you are looking for ranges, between can include the endpoints, in which case you could use return !d.before(min) && !d.after(max)

Upvotes: 7

bowmore
bowmore

Reputation: 11280

You can simply test the inverse :

!date1.after(date2)

You can always convert a strict order check to a non-strict check in this manner. Since mathematically :

a > b ⇔ ¬ (a ≤ b)

Upvotes: 69

taswyn
taswyn

Reputation: 4513

If the dates are equal, then obviously one is NOT before the other: false is the correct return for date1.before(date2) where date1 == date2.

If you need to include equality, why not do a negation on .after() (obviously if date 1 is NOT after date 2, then it is equal or before), but I would make sure that this is actually correct logic for what you are trying to accomplish.

If equality is a special case that needs to be handled differently, then have a separate test for .equals().

Upvotes: 10

svz
svz

Reputation: 4588

This is quite a normal behavior because dateBefore checks whether one date is before the other one. If the dates are equal this is obvious to be false.

Upvotes: 1

Related Questions