views:

504

answers:

7

How can I add two dates in Java?

Example: The sum of "2010-01-14 19:16:17" "0000-10-03 01:10:05"
would result in "2010-11-17 20:26:22".

I know how to do it using Calendar and adding field by field.

Is any other way to sum them all (year/month/day/hour/minute/second) at once?

+6  A: 

If you are using the Date object, you can just do:

Date d1 = ...
Date d2 = ...

long sum = d1.getTime() + d2.getTime();

Date sumDate = new Date(sum);

The code uses the .getTime() method that returns the number of milliseconds since the epoch. Needless to say the Date class has a lot of problems and should be avoided when possible.

Do you want to sum other types instead?

Update: for Calendar, I would do the following (based on javadocs):

Calendar c1 = ...
Calendar c2 = ...
long sum = c1.getTimeInMillis() + c2.getTimeInMillis();
Calendar sumCalendar = (Calendar)c1.clone();
sumCalendar.setTimeInMillis(sum);

UPDATED: As Steve stated, this works if the Date you presented here assumes that the second date is with respect to the Java epoch. If you do want to start with year "0", then you need to account for that (by subtracting your epoch time).

notnoop
This is just incorrect. Java's epoch is 1970. So using Date to represent a time duration (such as 0000-00-00 00:01 for one minute) will not work. Just try it and see.
Steve Kuo
Example: 1970-00-00 00:00 = 0 msec, so adding 1970-00-00 00:00 to 1970-00-00 00:00 using your algorithm yields 1970-00-00 00:00, where as the OP expects it to be 3940-00-00 00:00.
Steve Kuo
I store date/time as long so I just have to use + ;) No need to convert to Date/Calender and back again.
Peter Lawrey
As @Steve points out you cannot add two dates as the result is meaningless, You can add an interval to a date to get another date.
Peter Lawrey
@Peter. I cannot recommend using proper datatype classes for non-primitive concepts enough. Consider using jodatime or your own libary (if possible).
notnoop
@notnoop You are correct in most use cases. however in my case, 1) all our date-imes are in GMT 2) performance is an issue and we want to minimise or eliminate any object creation. As such all my date time operations, including parsing and outputting, can be performed without object creation.
Peter Lawrey
+6  A: 

As always, I would recommend Joda for date/time work, since it's much more powerful and intuitive.

You can add durations and periods to a DateTime object trivially. You can add minutes/seconds/months equally easily.

However, you can't add two dates directly, since that doesn't really make sense. This is a powerful illustration of why Joda is a help - it stops you doing stuff that you really shouldn't be doing.

Brian Agnew
+1, nice explanation.
Carl Smotricz
I don't like fascistic/paternalistic/communistic features of languages designed to stop me from doing what they think I shouldn't do because many times I need to do things that they think I shouldn't do.
Blessed Geek
Joda is a library, not a language.
Brian Agnew
+1 Joda time once saved my life! Err, project!
Helper Method
+3  A: 

You want to do getTimeInMillis() on both those Calendars so you'll have two honest-to-goodness long values you can add up. You can then take the sum and stash it in a new Calendar using that Calendar's setTimeInMillis() method.

Whether you want to add two Calendars as shown above or two Dates as shown in notnoop's answer is up to you, of course. The effect is similar, it just depends on what you want to do with the result. A Date is mostly just good for storing and/or converting to a String for printing out or displaying, whereas a Calendar will let you fiddle with the individual time values should you so choose.

As others have mentioned, you're committing some conceptual no-no's in using a Date or Calendar, which are meant to store "real" dates and times, e.g. ones in the 20th or 21st century, as intervals, i.e. time spans. The classes in the standard Java library don't give you really useful tools to handle this, which is why the Joda classes were developed. All the cool kids in date/time processing use those; but on the other hand that involves downloading and managing a 3rd party library.

Carl Smotricz
+2  A: 

notnoop answer is definitely correct. However, if you are going to do lots of processing of dates, times and intervals, I suggest that you look at class DateUtils in apache commons lang and at joda-time library.

JDK7 will come with better support for some of the features that joda-time provides. Just saying ... it might be a consideration if your app makes heavy usage of this stuff.

Yoni
+1 I strongly recommend joda-time. My impression is that the Time/Date API in Java 7 is basically dead! Do you know what the progress is?
notnoop
I believe that JSR310 is dead wrt. Java 7, yes. There's a question on SO somewhere that recently asked this very question (don't have the link to hand, I'm afraid).
Brian Agnew
+2  A: 

You need to define your EPOCH. The Java epoch (like Unix) is 1 Jan 1970 GMT/UTC. I assume you think you're adding ten months, 3 days and some odd hours from 1 Jan 0000 but you have a epoch offset until 1970. The maths may not necessarily work.

Use Calendar or Joda (as mentioned). If you just simply want to add a number of seconds and days (&c) then feel free to add said # of milliseconds to your first date object.

Xepoch
A: 

I am occasionally guilty of this practice too, storing time interval in a date object and using getTime() as suggested by notnoop.

It works. Contrary to certain opinion, it certainly works. I just ignore that the interval could be representative of an unintended date. It is a quick and dirty way for me to add an interval, say, [6 years, 6 months, 6 days, 6 hours, 6 minutes, 6 seconds] to a date.

Blessed Geek
right...but you're still adding 6m6d6h6s to 1970, not 0000.
Xepoch
+1  A: 

Don't sum the time in millis of the two dates!

Date d1 = new Date();
Date d2 = new Date();
Date dTotal = new Date(d1.getTime() + d2.getTime());
System.out.println(dTotal); // Incorrect! Misses about 1970 years.

Just clone the Calendar and add the datetime parts one by one.

Calendar c1 = Calendar.getInstance();
Calendar c2 = Calendar.getInstance();
Calendar cTotal = (Calendar) c1.clone();
cTotal.add(Calendar.YEAR, c2.get(Calendar.YEAR));
cTotal.add(Calendar.MONTH, c2.get(Calendar.MONTH) + 1); // Months are zero-based!
cTotal.add(Calendar.DATE, c2.get(Calendar.DATE));
cTotal.add(Calendar.HOUR_OF_DAY, c2.get(Calendar.HOUR_OF_DAY));
cTotal.add(Calendar.MINUTE, c2.get(Calendar.MINUTE));
cTotal.add(Calendar.SECOND, c2.get(Calendar.SECOND));
cTotal.add(Calendar.MILLISECOND, c2.get(Calendar.MILLISECOND));
System.out.println(cTotal.getTime()); // Correct!

Needless to say, JodaTime is smarter and cleaner with this.

BalusC
not sure if the Calendar solution works (despite OP wrote that he knows how to do it). The problem with Calendar: there is no year 0 (and missing treatment of *negative* years - when ERA == BC)
Carlos Heuberger