0

I have written the code like below, but it it is not working in below case.

LocalDate today = LocalDate.now(ZoneId.systemDefault());
DateTimrFormatter dobFormat = DateTimeFormatter.ofPattern("dd-MM-uuuu");
int age = Period.between(inputdate, today).getYears();
if (age >= 18 && age <= 75) {
    return true;
} else {
    return false
}

It is not checking age including days i.e. if we give input date as 24-06-1948, then age is 75 years + 2 days (greater than 75), but it returns true.

James Z
  • 12,209
  • 10
  • 24
  • 44
Nani K
  • 1
  • 2
  • 4
    This is a good opportunity for you to start familiarizing yourself with [using a debugger](https://stackoverflow.com/q/25385173/328193). When you step through the code in a debugger, which operation first produces an unexpected result? What were the values used in that operation? What was the result? What result was expected? Why? To learn more about this community and how we can help you, please start with the [tour] and read [ask] and its linked resources. – David Jun 26 '23 at 14:43
  • 3
    [`getYears()`](https://docs.oracle.com/javase/8/docs/api/java/time/Period.html#getYears--) returns an `int` so 75 years + 2 days has 75 years. – 001 Jun 26 '23 at 14:46
  • 1
    for 24-06-2948 is more than 75 (75 + 2days) - for this returns false. but in the above code it is returning true. Please suggest – Nani K Jun 26 '23 at 14:53
  • @NaniK read `001`'s comment. 75 is less than or equal to 75, so true. Now rethink whether there is anything else you can do with the Period. – Michael Jun 26 '23 at 14:58
  • If you obviously want to involve fractions of years, too, why don't you check months and days of the `Period`, too? – deHaar Jun 26 '23 at 15:27

4 Answers4

1

You can create new Period objects, and utilize the isZero and isNegative methods, to determine comparison.

Period minus18 = period.minusYears(18);
boolean gte18 = minus18.isZero() || !minus18.isNegative();
Period minus75 = period.minusYears(75);
boolean lte75 = minus75.isZero() || minus75.isNegative();
if (gte18 && lte75) {

} else {

}

Here is an example.

LocalDate today = LocalDate.now(ZoneId.systemDefault());
LocalDate[] dates = {
    LocalDate.of(1948, 6, 25), LocalDate.of(1948, 6, 26), LocalDate.of(1948, 6, 27),
    LocalDate.of(2005, 6, 25), LocalDate.of(2005, 6, 26), LocalDate.of(2005, 6, 27) };
Period period, minus18, minus75;
boolean gte18, lte75;
for (LocalDate inputdate : dates) {
    period = Period.between(inputdate, today);
    minus18 = period.minusYears(18);
    gte18 = minus18.isZero() || !minus18.isNegative();
    System.out.printf("%-12s - 18 = %-12s >= 18 = %b%n", period, minus18, gte18);
    minus75 = period.minusYears(75);
    lte75 = minus75.isZero() || minus75.isNegative();
    System.out.printf("%-12s - 75 = %-12s <= 75 = %b%n", period, minus75, lte75);
}

Output

P75Y1D       - 18 = P57Y1D       >= 18 = true
P75Y1D       - 75 = P1D          <= 75 = false
P75Y         - 18 = P57Y         >= 18 = true
P75Y         - 75 = P0D          <= 75 = true
P74Y11M30D   - 18 = P56Y11M30D   >= 18 = true
P74Y11M30D   - 75 = P-1Y11M30D   <= 75 = true
P18Y1D       - 18 = P1D          >= 18 = true
P18Y1D       - 75 = P-57Y1D      <= 75 = true
P18Y         - 18 = P0D          >= 18 = true
P18Y         - 75 = P-57Y        <= 75 = true
P17Y11M30D   - 18 = P-1Y11M30D   >= 18 = false
P17Y11M30D   - 75 = P-58Y11M30D  <= 75 = true
Reilas
  • 3,297
  • 2
  • 4
  • 17
0

I will recommend to use LocalDate, you can create two local date objects one with minimum date and another with maximum date

 LocalDate minDate = LocalDate.now().minusYears(18).minusDays(1);
 LocalDate maxDate = LocalDate.now().plusYears(57).plusDays(1);

Considering today's date as center point, you can create minDate with subtracting 18 years and 1 day, and the same way for maxDate of 75 years

Now you can use isBefore and isAfter methods to check in between condition

if(minDate.isBefore(toDayDate) && maxDate.isAfter(toDayDate))

Note : If you are looking for DOB check, always take DOB as center point

Ryuzaki L
  • 37,302
  • 12
  • 68
  • 98
  • if we give dob as 25-05-2005 (exact 18 years) it is also failing with above code – Nani K Jun 26 '23 at 15:45
  • DateTimeFormatter dobFormat = DateTimeFormatter.ofPattern("dd-MM-yyyy"); LocalDate inputDate = LocalDate.parse(dob,dobFormat); LocalDate minDate = LocalDate.now().minusYears(18).minusDays(1); LocalDate maxDate = LocalDate.now().plusYears(57).plusDays(1); if(minDate.isBefore(toDayDate) && maxDate.isAfter(toDayDate)){ return true; } else { return false; } ///Still it is failing if we give 26-06-1948 ///exact 75 years, still it is failing – Nani K Jun 26 '23 at 16:23
0

Former library Joda-time had the solution. See How do I calculate someone's age in Java?.

With the new Java-Time API we have two options:

  • Duration with compareTo, not suitable for months and years
  • Period with arithmetic, see Reilas 's answer
  • compare different LocalDates

Duration for short and precise (weeks, days, milli-/nano-seconds)

Usually we can use Duration when we need to compare objects to express temporal distance like age. The Duration class implements the Comparable interface and has a method compareTo(otherDuration).

This would work for approximate relative events like:

  • updated 5 minutes ago
  • next run in 2 weeks and 4 days

So, in theory we could compare the actual-age to a boundary like 18 years like actualAge.compareTo(AGE_18_YEARS) and evaluate the returned -1, 0 or 1. In practice the age-reference of AGE_18_YEARS must be specified as Duration which only allows ChronoUnit.Days as largest unit. How many days would be 18 years ?

Period based on calendar for long (especially months and years)

Unfortunately distant events like the age of a person take months and years. Both chrono-units depend on a calendar and their relative position. Months can be 28, 29, 30 or 31 days. Years can be 365, even 366 days for a leap-year.

LocalDate orientation within a calendar of birthdays

The age is special for any person, it has a special day and comprises a special number of days (depending on the birthday and leap-years).

Let's use the birthday to evaluate if someone is 18, in between or 75 years old.

Using a single concept like calendar, birthdays and date-comparison leads to a meaningful and readable solution.

Test the demo on IDEone:

// DOB: 2000-12-24
var dob =  LocalDate.of(2000, 12, 24);


// Minimum age: 18 years
var birthdayAge18years = dob.plusYears(18);
// Maximum age: 75 years
var birthdayAge75years = dob.plusYears(75);

var today = LocalDate.now();

// is today
//      on or after  18th birthday 
//  and on or before 75th birthday
var olderThanOr18 = today.equals(birthdayAge18years) || today.isAfter(birthdayAge18years);
var youngerThanOr75 = today.equals(birthdayAge75years) || today.isBefore(birthdayAge75years);

// test
System.out.println(birthdayAge18years + " > older than or exactly 18 years: " + olderThanOr18);
System.out.println(birthdayAge75years + " > younger than or exactly 75 years: " + youngerThanOr75);
hc_dev
  • 8,389
  • 1
  • 26
  • 38
-1

The issue is that getYears() returns the rounded number of full years, which is 75 in this case. So what you should really do is if (age >= 18 && age < 75).

That said, I have a few more remarks:

  1. Your question should not have syntax errors.
  2. You should really, really, learn to use a debugger if you want to pursue any form of professional software development career. It is a fundamental and essential skill.
  3. For future questions, please have a look at the StackOverflow code of conduct
mapawa
  • 179
  • 1
  • 4
  • 16
  • we need to return true if age is in between 18 and 75, otherwise we needs to return false – Nani K Jun 26 '23 at 16:32
  • I agree to most of your 3 meta-points. Still they distract from the answer. You could add a comment or [flag](https://stackoverflow.com/help/privileges/flag-posts) to the question directly. Not sure what's the specific issue in regards to SO's code of conduct. – hc_dev Jun 26 '23 at 17:50