user_01 - 1 year ago 161

Java Question

I would like to calculate exact age in days considering leap years. I researched on the web, found some tutorials, but with leap years that exactly calculates difference of dates in days seems to be the one in [1]: https://answers.yahoo.com/question/index?qid=20110629162003AAof4mT this link, which is "best answer" . I analyzed code but have two questions:

1) Why it writes "days = days + leapYears" below "Calculate days lives" section and

2) Finally, how can I input birthday date with day,month and year and current day,month,year and find difference of these two dates in days within this code in the main method? I really appreciate your help. Thanks in advance !

PS: For convenience, I have included the code from the link I showed above:

`public class Days {`

static int leapYear(int year) {

int leap;

if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)) {

leap = 1;

}

else {

leap = 0;

}

return leap;

}

static int daysBefore(int month, int day, int year){

int days = 0;

int monthDays[] = new int[] {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

if (leapYear(year) == 1){

monthDays[1] = 29;

}

for (int b = 0; b < month - 1; b++){

days = days + monthDays[b];

}

days = days + day;

return days;

}

public static void main(String[] args) {

//Birth date

int birthMonth = 0;

int birthDay = 0;

int birthYear = 0;

//Due date

int dueMonth = 0;

int dueDay = 0;

int dueYear = 0;

//(1) Calculate years lived

int yearsLived = dueYear - birthYear + 1;

//(2) Calculate leap years

int leapYears = 0;

for (int year = birthYear; year < dueYear+1; year++)

{

leapYears = leapYears + leapYear(year);

}

//(3) Calculate the number of days in your birth year before birth

int daysBeforeBirth = daysBefore(birthMonth, birthDay, birthYear);

//(4) Calculate the number of days remaining in the current year after the due date

int daysRemaining = 365 - daysBefore(dueMonth, dueDay, dueYear);

//Calculate days lived

int days = 0;

days = days + (365 * yearsLived);

days = days + leapYears;

days = days - daysBeforeBirth;

days = days - daysRemaining;

}

}

Answer Source

The correct way to do this is with the `Period`

and `LocalDate`

classes in the `java.time`

package. However, it seems that you're trying to reinvent the calculation for yourself.

The way that I would recommend doing this is to write a class that lets you calculate a "day number" for a given date - that is, the number of days between the specified date, and some arbitrary date in the past. Then when you want to find the number of days between two specified dates, you can just use calculate the "day number" for both dates, and subtract them.

I have done that here, for a purely Gregorian calendar. This class is no good before the Gregorian cutover - I haven't tried to build a historically accurate Julian/Gregorian hybrid calendar, such as the JDK provides. And the arbitrary date in the past that it calculates day numbers from is 31 December, 2BC. This date, of course, isn't really part of the Gregorian calendar; but for our purposes here, it doesn't matter.

Since you're unlikely to encounter any dates before the Gregorian cutover, this class should be more than adequate for your purposes. I still recommend using the `Period`

and `LocalDate`

classes instead of this one, for production code. This is just here so you can see how to do the calculations.

```
public class GregorianDate {
private final int day;
private final int month;
private final int year;
private static final int[] DAYS_PER_MONTH = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
public GregorianDate(int day, int month, int year) {
this.day = day;
this.month = month;
this.year = year;
}
public boolean isValid() {
return month >= 1 && month <= 12 && day >= 1 && day <= daysThisMonth();
}
public static int daysBetween(GregorianDate from, GregorianDate to) {
return to.dayNumber() - from.dayNumber();
}
public static int daysBetween(int fromDay, int fromMonth, int fromYear, int toDay, int toMonth, int toYear) {
return daysBetween(new GregorianDate(fromDay, fromMonth, fromYear), new GregorianDate(toDay, toMonth, toYear));
}
private int daysThisMonth() {
return (isLeapYear() && month == 2) ? 29 : DAYS_PER_MONTH[month];
}
private int dayNumber() {
return year * 365 + leapYearsBefore() + daysInMonthsBefore() + day;
}
private boolean isLeapYear() {
return ( year % 4 == 0 && year % 100 != 0 ) || year % 400 == 0;
}
private int leapYearsBefore() {
return year / 4 - year / 100 + year / 400;
}
private int daysInMonthsBefore() {
switch(month) {
case 1:
return 0;
case 2:
return 31;
default:
// Start with the number in January and February combined
int toReturn = isLeapYear() ? 60 : 59;
for (int monthToConsider = 3; monthToConsider < month; monthToConsider++) {
toReturn += DAYS_PER_MONTH[monthToConsider];
}
return toReturn;
}
}
}
```