spogebob92
spogebob92

Reputation: 1484

Checking if difference between two dates in greater than a year - Java

I have a date, and I want to see if that date is further/less than 1 year away from today. For example, the the date is 13th May 2017, it would return true, if it was 13th May 2018, it would return false.

The bug at the moment in my code is that it would return true for December 2014 (which should return false).

Any ideas?

private boolean checkIfDateIsInRange() {
        Calendar today = DateTimeHelper.dateToCalendar(new Date());
        if (currentDate.get(Calendar.YEAR) > today.get(Calendar.YEAR) + 1 || currentDate.get(Calendar.YEAR) < today.get(Calendar.YEAR) - 1){
            return false;
        }
        return true;
    } 

The dateToCalendar method is as follows:

public static Calendar dateToCalendar(Date date){
    Calendar cal = Calendar.getInstance();
    cal.setTime(date);
    return cal;
}

Upvotes: 0

Views: 5683

Answers (8)

klabe
klabe

Reputation: 495

startDate.plusYears(1).isBefore(endDate);

I find the code pretty self explanatory. Rather than measuring the difference between the two dates, adding a year to the first date and comparing is simpler. The code works if startDate and endDate have type LocalDate or ZonedDateTime or OffsetDateTime or LocalDateTime.

Upvotes: 1

Basil Bourque
Basil Bourque

Reputation: 338211

tl;dr

see if that date is further/less than 1 year away from today

Use LocalDate.isAfter for comparison.

LocalDate.of( 2020 , Month.JANUARY , 23 ).isAfter(
    LocalDate.now().plusYears( 1 )  // Better to pass an explicit time zone than rely on the JVM’s current default: LocalDate.now( ZoneId.of( “Pacific/Auckland” ) )
)

Details

The modern approach uses the java.time classes. For earlier Android see the back-port project, ThreeTenABP.

Determine today’s date requires a time zone. For any given moment the date varies around the globe by zone. For example, today in Paris France early morning is still “yesterday” in Montréal Québec.

ZoneId z = ZoneId.of( “Africa/Tunis” ) ;

The LocalDate class represents a date-only value without time of day and without time zone.

LocalDate today = LocalDate.now( z ) ;

Calculate a year into future.

LocalDate yearFromToday = today.plusYears( 1 ) ;

Instantiate your date.

LocalDate x = LocalDate.of( 2020 , Month.JANUARY , 23 ) ;

Compare.

Boolean isOverYearInFuture = x.isAfter( yearFromToday ) ;

About java.time

The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.

To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.

Where to obtain the java.time classes?

Upvotes: 1

OPMendeavor
OPMendeavor

Reputation: 460

I have the same need and found the official jdk answer. It gives the indication to use Period for such kind of check on dates:

I found the functionality so useful!

SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");

int numYear = 1;
//checking if the period is more than the specified number of years (last parameter)
if(checkForPeriodLimit(sdf.parse("12/04/1977"), sdf.parse("11/04/1978"), numYear)){
     System.out.println("less than"+numYear+" year ago");
} else {
    System.out.println("more than"+numYear+" year ago");
}

//period checking function
public boolean checkForPeriodLimit(Date dateFrom, Date dateTo, int periodInYear){

    Period p = Period.between(dateFrom.toInstant().atZone(ZoneId.systemDefault()).toLocalDate(),
            dateTo.toInstant().atZone(ZoneId.systemDefault()).toLocalDate());

    return ((p.getYears() < periodInYear)?true:false);
}

Print the result:

**less than 1 years ago**

Upvotes: 0

Titus
Titus

Reputation: 22474

You can do something like this:

if(TimeUnit.MILLISECONDS.toDays((long)Math.abs(today.getTimeInMillis() - currentDate.getTimeInMillis())) >= 365){
    // Is one or more years after or before.
}

If you want to account for leap years, you can do this:

final GregorianCalendar gc = new GregorianCalendar();
public boolean moreTheOneYearDifference(Calendar c1, Calendar c2){
    int days = 365;
    if (c1.before(c2) && gc.isLeapYear(c1.get(Calendar.YEAR))) {
        days += 1;
    } else if (gc.isLeapYear(c2.get(Calendar.YEAR))) {
        days += 1;
    }
    return TimeUnit.MICROSECONDS.toDays((long)Math.abs(c1.getTimeInMillis() - c2.getTimeInMillis())) >= days
}

Upvotes: 0

Narmer
Narmer

Reputation: 1454

Just adding another way to do it:

public boolean checkIfInRange(Date date){

    Calendar cal= Calendar.getInstance();

    cal.add(Calendar.YEAR, -1);
    Date yearBeforeToday = cal.getTime();
    cal.add(Calendar.YEAR, 2);
    Date yearAfterToday = cal.getTime();

    return date.after(yearBeforeToday) && date.before(yearAfterToday);
}

Try it online!

Upvotes: 0

user6073886
user6073886

Reputation:

Your solution is only checking if the year part of the dates has a greater difference then 1, which of course will produce incorrect results for values like 2015-1-1 and 2016-12-31.

I would recomment adding a year to the lower of the two dates (after cloning it ofc.) and then checking if it is still before the later date, in which case the difference is more than a year.

public static boolean isMoreThanAYearDifference(Calendar c1, Calendar c2) {
    final Calendar earlierDate;
    final Calendar laterDate;
    if(c1.before(c2)) {
        earlierDate = (Calendar) c1.clone();
        laterDate = c2;
    } else {
        earlierDate = (Calendar) c2.clone();
        laterDate = c1;
    }

    earlierDate.add(Calendar.YEAR, 1);
    return earlierDate.before(laterDate);
}

Upvotes: 0

Fildor
Fildor

Reputation: 16059

Given today is a Calendar of the actual date and dateInQuestion is a Calendar of the date to be checked:

Calendar oneYearPlus  = (today.clone()).add(Calendar.YEAR,1);
Calendar oneYearAgo   = (today.clone()).add(Calendar.YEAR,-1);
return oneYearPlus.after(dateInQuestion) || oneYearAgo.before(dateInQuestion);

Upvotes: 0

Aditya Vyas-Lakhan
Aditya Vyas-Lakhan

Reputation: 13555

I suggest you to use Joda Times and you can find Years Between

public static Years yearsBetween(ReadableInstant start,
                                 ReadableInstant end)

Upvotes: 2

Related Questions