1

I have 2 dates as input. I wish to count a number of years between them. When there is less than 1 year, I wish to get a double (i.e 0.xyz) as output. I have tried the function below:

private double getYearCount(Date startDate, Date endDate)
{
        long millisecondCount = endDate.getTime() - startDate.getTime();
        long yearMillisecondCount = 1000L * 60L * 60L * 24L * 365L;
        return millisecondCount / (double) yearMillisecondCount;
}

But I have assumed there, that the year is 365 days long. So the leap year is not taken into attention. The 2 dates could have different years(for example they could be 01.01.1987 and 07.01.2013).

How can I fix it so, that I take into attention also also leap years?

Roman C
  • 49,761
  • 33
  • 66
  • 176
user897237
  • 613
  • 5
  • 12
  • 25
  • If you manipulate dates / times, consider using the JodaTime library ! – Romain Linsolas Jan 20 '13 at 21:00
  • you want... java.util.GregorianCalendar ;-) – ggrandes Jan 20 '13 at 21:02
  • 5
    There is an ambiguity here introduced by leap years. Do you want to measure a fractional year as a fraction of a leap year (366 days), a fraction of a non-leap year(365) days, or as a fraction of an average year(365.2425 days)? – President James K. Polk Jan 20 '13 at 21:04
  • Hi, I don't want an average... cause if i use an average for year 2012(start date 1.1.12 , endate 31.12.12 I would not get 1.It would be easy if endyear and startyear are same.. but what should i do if the dates are different? – user897237 Jan 21 '13 at 00:44
  • Using a decimal number to represent such a span of time is often not helpful. Consider the [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601#Durations) standard format. The *java.time* classes `Period` and `Duration` use that standard format by default when parsing/generating strings. – Basil Bourque Jan 23 '18 at 05:01

2 Answers2

0

Just use the correct time for a year. Which is 365.2425 days.

However, this is not recommended. Use a time/date library to determine the year for both years, and subtract them.

Initialize a GregorianCalendar for both dates, and get the years.

Martijn Courteaux
  • 67,591
  • 47
  • 198
  • 287
0

I wrote a method that returns the number of years and days in a date range. As James K. Polk mentioned in his comment, you can divide the days by 365, 365.2425, or 366 to get the fractional part of a year.

Here are the test results.

From 01 Jan 1987 to 01 Jul 2013 is an interval of 26 years and 182 days.
From 01 Jul 2012 to 01 Jul 2013 is an interval of 1 years and 1 days.
From 01 Jul 2012 to 31 Jul 2012 is an interval of 0 years and 31 days.
From 01 Apr 2012 to 31 Dec 2012 is an interval of 0 years and 275 days.

And here's the code. Basically, I'm counting the years and days one by one from the start date to the end date.

This code works with Java 6, Java 7, and beyond.

package com.ggl.testing;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

public class DateRangeCalculator {

    private static final SimpleDateFormat format = new SimpleDateFormat(
            "dd MMM yyyy");

    public static void main(String[] args) {
        DateRangeCalculator dateRangeCalculator = new DateRangeCalculator();
        calculateDateInterval(dateRangeCalculator, "01 Jan 1987", "01 Jul 2013");
        calculateDateInterval(dateRangeCalculator, "01 Jul 2012", "01 Jul 2013");
        calculateDateInterval(dateRangeCalculator, "01 Jul 2012", "31 Jul 2012");
        calculateDateInterval(dateRangeCalculator, "01 Apr 2012", "31 Dec 2012");
    }

    private static void calculateDateInterval(
            DateRangeCalculator dateRangeCalculator, String startDateString,
            String endDateString) {
        try {
            Date startDate = format.parse(startDateString);
            Date endDate = format.parse(endDateString);
            DateInterval dateInterval = dateRangeCalculator.getDateInterval(
                    startDate, endDate);
            System.out.println("From " + format.format(startDate) + " to "
                    + format.format(endDate) + " is an interval of "
                    + dateInterval.getYears() + " years and "
                    + dateInterval.getDays() + " days.");
        } catch (ParseException e) {
            e.printStackTrace();
        }
    }

    public DateInterval getDateInterval(Date startDate, Date endDate) {
        Calendar startCalendar = createCalendar(startDate);
        Calendar endCalendar = createCalendar(endDate);

        int years = -1;
        while (!startCalendar.after(endCalendar)) {
            startCalendar.add(Calendar.YEAR, 1);
            years++;
        }

        startCalendar.add(Calendar.YEAR, -1);

        int days = 0;
        while (!startCalendar.after(endCalendar)) {
            startCalendar.add(Calendar.DAY_OF_YEAR, 1);
            days++;
        }

        return new DateInterval(years, days);
    }

    private Calendar createCalendar(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar;
    }

    public class DateInterval {
        private final int years;
        private final int days;

        public DateInterval(int years, int days) {
            this.years = years;
            this.days = days;
        }

        public int getYears() {
            return years;
        }

        public int getDays() {
            return days;
        }

    }

}
Community
  • 1
  • 1
Gilbert Le Blanc
  • 50,182
  • 6
  • 67
  • 111