Search code examples
javadatedatetimedifferencedate-difference

Java Difference between current date and past date in Years, Months, Days, Hours, Minutes, Seconds


I know this has been asked on here many times previously, but I'm haven't been able to find anything specific to my case. I'm trying to find the difference between the current datetime and a previous datetime, each with the format yyyy-MM-dd HH:mm:ss.s. Based on the answer given here, I've come up with the following code:

SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.s");
String earliestRunTime = "2017-12-16 01:30:08.0";
Date currentDate = new Date();
log.info("Current Date: {}", format.format(currentDate));

try {
    Date earliestDate = format.parse(earliestRunTime);

    long diff = currentDate.getTime() - earliestDate.getTime();

    long diffSeconds = diff / 1000 % 60;
    long diffMinutes = diff / (60 * 1000) % 60;
    long diffHours = diff / (60 * 60 * 1000) % 24;
    long diffDays = diff / (24 * 60 * 60 * 1000) % 30;
    long diffMonths = diff / (30 * 24 * 60 * 60 * 1000) % 12;
    long diffYears = diff / (12 * 30 * 24 * 60 * 60 * 1000);

    return String.format("%s years, %s months, %s days, %s hours, %s minutes, %s seconds",
            diffYears, diffMonths, diffDays, diffHours, diffMinutes, diffSeconds);


    }
catch (Exception e) {
    e.printStackTrace();
    return e.getMessage();
}

When I run the code, the JSON returns the following result:

lifetime: "41 years, -1 months, 14 days, 9 hours, 42 minutes, 37 seconds"

I have two questions here:

  1. Where am I going wrong in my calculations 41 years and a negative number?
  2. Is there a better way for me to do this? My current setup does not consider leap years or a 365 day year, and I need to take these into account.

Solution

  • Using the same approach you did, you need to explicitly identify the denominator as long values. Currently, it assumes them to be integers, which causes a numeric overflow - meaning the value computed is too large for a integer. This would explain why you get negative/arbitrary values. Fix is simple:

    SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.s");
    String earliestRunTime = "2017-12-16 01:30:08.0";
    Date currentDate = new Date();
    log.info("Current Date: {}" + format.format(currentDate));
    
    try {
        Date earliestDate = format.parse(earliestRunTime);
    
        long diff = currentDate.getTime() - earliestDate.getTime();
    
        long diffSeconds = diff / 1000L % 60L;
        long diffMinutes = diff / (60L * 1000L) % 60L;
        long diffHours = diff / (60L * 60L * 1000L) % 24L;
        long diffDays = diff / (24L * 60L * 60L * 1000L) % 30L;
        long diffMonths = diff / (30L * 24L * 60L * 60L * 1000L) % 12L;
        long diffYears = diff / (12L * 30L * 24L * 60L * 60L * 1000L);
    
        return String.format("%s years, %s months, %s days, %s hours, %s minutes, %s seconds",
                diffYears, diffMonths, diffDays, diffHours, diffMinutes, diffSeconds);
    
    
    }
    catch (Exception e) {
        e.printStackTrace();
        return e.getMessage();
    }