2

I have three dates as String objects in the format: dd:HH:mm:ss

  • 00:1:9:14
  • 00:3:10:4
  • 00:3:39:49

How do I add these dates in Java to get the sum (00:7:59:07)?

Sample code:

SimpleDateFormat sdf = new SimpleDateFormat("dd:HH:mm:ss");
Date d1 = sdf.parse("00:1:9:14");
Date d2 = sdf.parse("00:3:10:4");
Date d3 = sdf.parse("00:3:39:49");

System.out.println(d1);
System.out.println(d2);
System.out.println(d3);
Date d = new Date(d1.getTime() + d2.getTime() + d3.getTime());

System.out.println(d);

Output(wrong):

Wed Dec 31 01:09:14 IST 1969
Wed Dec 31 03:10:04 IST 1969
Wed Dec 31 03:39:49 IST 1969
Sun Dec 28 20:59:07 IST 1969
ifloop
  • 8,079
  • 2
  • 26
  • 35
Kalyan Ghosh
  • 483
  • 11
  • 12
  • 2
    How do you expect to be able to add dates? What is "December 14th, 2008" plus "October 12th, 2013"? – jarnbjo Nov 06 '14 at 17:57
  • 1
    [This thread](http://stackoverflow.com/questions/2067657/sum-two-dates-in-java) seems to want to do the same thing. In short, sum the total of milliseconds since epoch and create a new date based on the result. – mattias Nov 06 '14 at 17:58
  • @mattias: Be aware that the accepted answer to the question you're linking to is completely wrong. – jarnbjo Nov 06 '14 at 18:00
  • @jambjo: Yeah, and when thinking about it, I guess rather than summing up actual date values, the problem at hand might be to calculate two "Timer values" represented as date objects. As you so perfectly stated, what would be the benefit/business value of summing the year 2008 with the year 2013. – mattias Nov 06 '14 at 18:03
  • Use [`java.time.Duration`](https://docs.oracle.com/javase/10/docs/api/java/time/Duration.html). Beware that it always counts a day as 24 hours, which it isn’t always, though. – Ole V.V. Apr 17 '20 at 15:33
  • 1
    FYI, the terribly flawed date-time classes such as [`java.util.Date`](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/Date.html), [`java.util.Calendar`](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/Calendar.html), and `java.text.SimpleDateFormat` are now [legacy](https://en.wikipedia.org/wiki/Legacy_system), supplanted by the [*java.time*](https://docs.oracle.com/javase/tutorial/datetime/TOC.html) classes built into Java 8 and later. – Basil Bourque Apr 17 '20 at 22:18

5 Answers5

2

The dd format includes the day of the month. So your value of 00 will underflow if you use SimpleDateFormat (or Java Date because it also includes a day of the month). Instead, parse your time parts and do the math yourself.

For example, you could create a class TimePart with days, hours, minutes and seconds like

static class TimePart {
    int days = 0;
    int hours = 0;
    int minutes = 0;
    int seconds = 0;

    static TimePart parse(String in) {
        if (in != null) {
            String[] arr = in.split(":");
            TimePart tp = new TimePart();
            tp.days = ((arr.length >= 1) ? Integer.parseInt(arr[0]) : 0);
            tp.hours = ((arr.length >= 2) ? Integer.parseInt(arr[1]) : 0);
            tp.minutes = ((arr.length >= 3) ? Integer.parseInt(arr[2]) : 0);
            tp.seconds = ((arr.length >= 4) ? Integer.parseInt(arr[3]) : 0);
            return tp;
        }
        return null;
    }

    public TimePart add(TimePart a) {
        this.seconds += a.seconds;
        int of = 0;
        while (this.seconds >= 60) {
            of++;
            this.seconds -= 60;
        }
        this.minutes += a.minutes + of;
        of = 0;
        while (this.minutes >= 60) {
            of++;
            this.minutes -= 60;
        }
        this.hours += a.hours + of;
        of = 0;
        while (this.hours >= 24) {
            of++;
            this.hours -= 24;
        }
        this.days += a.days + of;
        return this;
    }

    @Override
    public String toString() {
        return String.format("%02d:%02d:%02d:%02d", days, hours, minutes,
                seconds);
    }
}

Then your test-cases like

public static void main(String[] args) {
    try {
        TimePart d1 = TimePart.parse("00:1:9:14");
        TimePart d2 = TimePart.parse("00:3:10:4");
        TimePart d3 = TimePart.parse("00:3:39:49");
        System.out.println(d1);
        System.out.println(d2);
        System.out.println(d3);
        TimePart d4 = d1.add(d2).add(d3);
        System.out.println(d4);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

And it seems to perform the addition correctly like

00:01:09:14
00:03:10:04
00:03:39:49
00:07:59:07
Elliott Frisch
  • 198,278
  • 20
  • 158
  • 249
1

The above sum is arithmetic addition so you need a ref --here d0 (default epoch). Date class has a lot of problems beware...

SimpleDateFormat sdf = new SimpleDateFormat("dd:HH:mm:ss");
Date d0 = sdf.parse("00:00:00:00"); // ref 
Date d1 = sdf.parse("00:01:09:14");
Date d2 = sdf.parse("00:03:10:04");
Date d3 = sdf.parse("00:03:39:49");

System.out.println(d0);
System.out.println(d1);
System.out.println(d2);
System.out.println(d3);
Date d = new Date(d1.getTime() + d2.getTime() + d3.getTime() - 2 * d0.getTime()); // impt

System.out.println(d);

Note:- Date addition is not an easy task, think twice.

Mitesh Pathak
  • 1,306
  • 10
  • 14
1
SimpleDateFormat format = new SimpleDateFormat("HH:mm:ss");    

String s1 = "01:02:03";
String s2 = "10:12:13";

Date d1 = format.parse(s1);
Date d2 = format.parse(s2);

int sec = d1.getSeconds() + d2.getSeconds();
int min = d1.getMinutes() + d2.getMinutes();
int hr = d1.getHours() + d2.getHours();

Time sum = new Time(hr, min, sec);
System.out.println(sum); // Output: 11:14:16
1

Do your strings represent/denote amounts of time? So use the Duration class. Let’s first write an auxiliary method that parses a string into a Duration:

private static Duration parseDuration(String timeString) {
    // First convert the string to ISO 8601 through a regex
    String isoTimeString = timeString.replaceFirst("^(\\d+):(\\d+):(\\d+):(\\d+)$", "P$1DT$2H$3M$4S");
    // Then parse into Duration
    return Duration.parse(isoTimeString);
}

Duration.parse() requires ISO 8601 format, it goes like PT1H9M14S for a period of time of 1 hour 9 minutes 14 seconds. Or optionally P0DT1H9M14S. The 0D for 0 days goes before the T. So I use a regular expression (AKA a regex) to modify your string format into ISO 8601 before parsing it. The $1, $2, etc., in the replacement string refer to what was matched inside the round brackets, the so-called groups in the regular expression.

Now we can add the times up:

    String[] timeStrings = { "00:1:9:14", "00:3:10:4", "00:3:39:49" };

    Duration totalTime = Duration.ZERO;
    for (String timeString : timeStrings) {
        Duration dur = parseDuration(timeString);
        totalTime = totalTime.plus(dur);
    }

    System.out.println(totalTime);

Output:

PT7H59M7S

7 hours 59 minutes 7 seconds. If you want, you may format it back into your format of 00:7:59:07. Search for how.

What went wrong in your code?

Your first mistake seems to have been before writing the code: thinking of the times as dates. They are not, and it would not make any sense to add dates. What is the sum of April 7 and December 25?

Mislead by this thinking, you tried to parse into Date objects. A Date is a point in time, not an amount of time, so this is wrong. Other than that the Date class is poorly designed, and the SimpleDateFormat class that you also tried to use is notoriously troublesome. Fortunately we’ve got no use for them here, and also for dates and times they are long outdated, superseded by java.time, the modern Java date and time API, of which Duration is but one of many classes.

Links

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
  • That is some fancy regex you did there! I do suggest you add a mention that it actually is regex, for the readers who might not be aware. – Basil Bourque Apr 17 '20 at 22:21
  • I would move that mention of regex *before* the source code. This acts as narration, telling me what to expect as I my eye moves to study the code. – Basil Bourque Apr 18 '20 at 05:41
  • Thanks, @BasilBourque, for the suggestion. I see your point. My style is more for presenting the concrete, the code, first, and explaining at afterward. As a compromise? No, I think it’s actually helpful this way, I have mentioned the regex in a comment in the code preceding that code line. – Ole V.V. Apr 18 '20 at 05:48
0
private static String addTimes(String time1, String time2) throws ParseException {
    SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");

    Calendar c1 = Calendar.getInstance();
    Calendar c2 = Calendar.getInstance();
    c1.setTime(dateFormat.parse(time1));
    c2.setTime(dateFormat.parse(time2));

    c1.add(Calendar.HOUR, c2.get(Calendar.HOUR));
    c1.add(Calendar.MINUTE, c2.get(Calendar.MINUTE));
    c1.add(Calendar.SECOND, c2.get(Calendar.SECOND));
    return dateFormat.format(c1.getTime());
}

addTimes("1:9:14", "3:10:4");    

Output: 04:19:18

Milan Paudyal
  • 519
  • 9
  • 11
  • 1
    (1) The `Calendar` class is long outdated and poorly designed. I recommend we don’t use it. (2) A `Calendar` is a date and time of day (with time zone, week numbering scheme, etc.). It is *not* a duration, an amount of time. – Ole V.V. Apr 17 '20 at 16:25