Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Check if date between date range that also handle null values Java

My standard method for checking if a date is between two dates in Java looks like this:

public static boolean isWithinRange(Date date, Date startDate, Date endDate) {
    return !(date.before(startDate) || date.after(endDate));
}

I want to add support for null values on startDate or endDate (meaning user hasn't entered a date. If startDate is null I only want to check endDate and if endDate is null I only want to check startDate and if both null then it is true. My current solution looks like this:

public static boolean isWithinRange(Date date, Date startDate, Date endDate) {
    if (startDate == null && endDate == null) {
        return true;
    }

    if (!(startDate != null || !date.after(endDate))) {
        return true;
    }

    if (!(endDate != null || !date.before(startDate))) {
        return true;
    }

    return !(date.before(startDate) || date.after(endDate));
}

alternative more readable example:

public static boolean isWithinRange(Date date, Date startDate, Date endDate) {
    if (startDate == null && endDate == null) {
        return true;
    }

    if (startDate == null && date.before(endDate))) {
        return true;
    }

    if (endDate == null && date.after(startDate))) {
        return true;
    }

    return date.after(startDate) && date.before(endDate));
}

But it feels like really bad code. Is there any other way to deal with this?

like image 209
uraza Avatar asked Oct 26 '16 11:10

uraza


2 Answers

How about:

return (startDate == null || !date.before(startDate))
    && (endDate == null || !date.after(endDate));

This uses the fact that these two statements are equivalent:

!(date.before(startDate) || date.after(endDate))
!date.before(startDate) && !date.after(endDate)

And the fact that || is a short-circuit, which prevents NullPointerExceptions.

like image 55
assylias Avatar answered Sep 30 '22 01:09

assylias


Java 8's enhances to the Comaparator interface provide a pretty elegant way of doing this:

private static final Comparator<Date> NULL_SAFE_BEFORE =
        Comparator.nullsFirst(Comparator.naturalOrder());

private static final Comparator<Date> NULL_SAFE_AFTER =
        Comparator.nullsLast(Comparator.naturalOrder());

public static boolean isWithinRange(Date date, Date startDate, Date endDate) {
    return NULL_SAFE_BEFORE.compare(startDate, date) < 0 &&
            NULL_SAFE_AFTER.compare(date, endDate) < 0;
}
like image 30
Mureinik Avatar answered Sep 30 '22 02:09

Mureinik