5

Possible Duplicate:
Calculating difference in dates in Java
How do you subtract Dates in Java?

I am parsing two dates from a string that look like:

Oct 15, 2012 1:07:13 PM
Oct 23, 2012 03:43:34 PM

What I need to do is find the difference between these two dates, ex:

Oct 23, 2012 03:43:34 PM - Oct 15, 2012 1:07:13 PM

= 8 days 2 hours 36 minutes 21 seconds

^ This is what I need to get with the two date/times I have

I believe I need to parse the format and convert it to another format, then subtract the difference between and do the math to get the days/hours/minutes/seconds between

Community
  • 1
  • 1
Jsn0605
  • 203
  • 3
  • 5
  • 13
  • Above duplicate is only valid in combination with http://stackoverflow.com/questions/4216745/java-string-to-date-conversion in order to convert `String` to `Date` first. You might want to look at Joda Time as well: http://stackoverflow.com/questions/2179644/how-to-calculate-elapsed-time-from-now-with-joda-time – BalusC Oct 23 '12 at 18:34
  • 1
    Use [Joda Time](http://joda-time.sourceforge.net/) – Piotr Gwiazda Oct 23 '12 at 18:35

3 Answers3

12

In contrary to what other answerers try to imply, calculating the difference between two dates isn't that trivial in standard Java SE.

Your first step is indeed to convert those strings to useable Date instances. You can do this using SimpleDateFormat. Here's a kickoff example:

String string1 = "Oct 15, 2012 1:07:13 PM";
String string2 = "Oct 23, 2012 03:43:34 PM";

SimpleDateFormat sdf = new SimpleDateFormat("MMM d, yyyy h:mm:ss a", Locale.ENGLISH);

Date date1 = sdf.parse(string1);
Date date2 = sdf.parse(string2);

(please note the importance of the optional Locale argument here, this is often overlooked in answers about converting strings to dates)

Your next step is calculating the difference between those 2 dates. This is a terrible job when you are restricted to the standard Java SE API. Best what you can get is the java.util.Calendar.


Note that you could of course substract the milliseconds and calculate the difference using the usual arithmetic operators.

long differenceInMillis = date2.getTime() - date1.getTime();
// ...

But this naive approach doesn't take leap years into account, let alone daylight saving time and local-specific changes in datetime.


As to the java.util.Calendar approach, you basically need to use Calendar#add() in a counter loop to get the elapsed value for years, months and days. This takes leap years, daylight saving time and local-specific disturbances in time properly into account.

First create this helper method to eliminate some boilerplate code:

public static int elapsed(Calendar before, Calendar after, int field) {
    Calendar clone = (Calendar) before.clone(); // Otherwise changes are been reflected.
    int elapsed = -1;
    while (!clone.after(after)) {
        clone.add(field, 1);
        elapsed++;
    }
    return elapsed;
}

Now you can calculate the elapsed time as follows:

Calendar start = Calendar.getInstance();
start.setTime(date1);
Calendar end = Calendar.getInstance();
end.setTime(date2);

Integer[] elapsed = new Integer[6];
Calendar clone = (Calendar) start.clone(); // Otherwise changes are been reflected.
elapsed[0] = elapsed(clone, end, Calendar.YEAR);
clone.add(Calendar.YEAR, elapsed[0]);
elapsed[1] = elapsed(clone, end, Calendar.MONTH);
clone.add(Calendar.MONTH, elapsed[1]);
elapsed[2] = elapsed(clone, end, Calendar.DATE);
clone.add(Calendar.DATE, elapsed[2]);
elapsed[3] = (int) (end.getTimeInMillis() - clone.getTimeInMillis()) / 3600000;
clone.add(Calendar.HOUR, elapsed[3]);
elapsed[4] = (int) (end.getTimeInMillis() - clone.getTimeInMillis()) / 60000;
clone.add(Calendar.MINUTE, elapsed[4]);
elapsed[5] = (int) (end.getTimeInMillis() - clone.getTimeInMillis()) / 1000;

System.out.format("%d years, %d months, %d days, %d hours, %d minutes, %d seconds", elapsed);

Pretty ugly, yeah.

If you going to work with date and time in Java pretty often, then you may find Joda time the walhalla. Here's a concrete kickoff example of how you could do it all with pure Joda Time:

String string1 = "Oct 15, 2012 1:07:13 PM";
String string2 = "Oct 23, 2012 03:43:34 PM";

DateTimeFormatter dtf = DateTimeFormat.forPattern("MMM d, yyyy h:mm:ss a").withLocale(Locale.ENGLISH);

DateTime dateTime1 = dtf.parseDateTime(string1);
DateTime dateTime2 = dtf.parseDateTime(string2);
Period period = new Period(dateTime1, dateTime2);

PeriodFormatter formatter = new PeriodFormatterBuilder()
    .appendYears().appendSuffix(" years ")
    .appendMonths().appendSuffix(" months ")
    .appendWeeks().appendSuffix(" weeks ")
    .appendDays().appendSuffix(" days ")
    .appendHours().appendSuffix(" hours ")
    .appendMinutes().appendSuffix(" minutes ")
    .appendSeconds().appendSuffix(" seconds ")
    .printZeroNever()
    .toFormatter();

String elapsed = formatter.print(period);
System.out.println(elapsed);

Much better, right? The plural "s" needs some work though, but that's beyond the question.

Community
  • 1
  • 1
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • this is exactly what I need, works awesome. But it is a minor issue. If a year is bigger than 10 000 it affects on calculating speed because of the loop in the `public static int elapsed(Calendar before, Calendar after, int field);` function. I tried to subtract a current year from a target one without looping, and the result is unpredictable. What can I do to be able process years bigger than 10 000 with out slowing processing speed? – Bob May 13 '16 at 11:21
0

You need to use SimpleDateFormat to parse String and create Date

Then you can find the difference between dates.

Here is javadoc for SimpleDateFormat

kosa
  • 65,990
  • 13
  • 130
  • 167
-4

try this:

Calendar ca1 = Calendar.getInstance();
ca1.set(2012,05,25);
// Addition of date in java        
ca1.add(Calendar.DATE, 23); // Add 23 days in Dates in Calendar
ca1.add(Calendar.MONTH, 2); // Add 2 Month in Date in Calendar
ca1.add(Calendar.YEAR, 4); // add 4 Year in Date in Calendar

ca1.add(Calendar.DATE, -23); // sub 23 days in Dates in Calendar
ca1.add(Calendar.MONTH, -2); // sub 2 Month in Date in Calendar
ca1.add(Calendar.YEAR, -4); // sub 4 Year in Date in Calendar
Jared Burrows
  • 54,294
  • 25
  • 151
  • 185
Bhanu Kaushik
  • 876
  • 6
  • 25