Domanda

I have the following method to sum time:

public static String sumTime(String date1, String date2) throws ParseException {
    Calendar calendar = Calendar.getInstance();
    SimpleDateFormat formatter = new SimpleDateFormat("HH:mm:ss.SSS");

    Date d1 = formatter.parse(date1);
    Date d2 = formatter.parse(date2);
    calendar.setTime(d2);

    d1 = DateUtils.addHours(d1, calendar.get(Calendar.HOUR_OF_DAY));
    d1 = DateUtils.addMinutes(d1, calendar.get(Calendar.MINUTE));
    d1 = DateUtils.addSeconds(d1, calendar.get(Calendar.SECOND));
    d1 = DateUtils.addMilliseconds(d1, calendar.get(Calendar.MILLISECOND));

    return formatter.format(d1);
}

DateUtils is from Apache Commons Lang 3
It works quite well for what I want, unless the sum is bigger than 24 hours.


For example:

String time = "00:00:00.000";

try {
    for (int i = 0; i < 24; i++) {
            time = sumTime(time, "01:00:00.123");
    }

    System.out.println(time);
} catch (ParseException e) {
    e.printStackTrace();
}

The result is:

00:00:02.952

But this is what I'd like it to be:

24:00:02.952


Is there any (easy) way to accomplish that?
I don't mind using different libraries/methods, as long as I get the correct result.


Keep in mind that time will always start in 00:00:00.000;

È stato utile?

Soluzione

Date is not the right thing class to use. Date is a instant of time, not a "Date Difference".

The right thing to do will be to use a library like Joda Time as someone has already suggested. If you don't want to do so - here's a possible alternative:

Parse the string into hours, minutes and seconds yourself, and then add it yourself.

I would encourage you to look into a "well accepted" library though. There may be things I'm not thinking of in my solution. Also, you have add all the error checking.

Here's the starter code:

public class TimeInterval {
short milliSeconds;
short seconds;
short minutes;
int hours;

public TimeInterval (String dateString) {
    // HHHHHH:MI:SS.SSS
    Pattern pattern = Pattern.compile("(\\d+):(\\d\\d):(\\d\\d)\\.(\\d\\d\\d)");
    Matcher matcher = pattern.matcher(dateString);
    if ( matcher.find() ) {
        hours = Integer.parseInt(dateString.substring(matcher.start(1), matcher.end(1)));
        minutes = Short.parseShort(dateString.substring(matcher.start(2), matcher.end(2)));
        seconds = Short.parseShort(dateString.substring(matcher.start(3), matcher.end(3)));
        milliSeconds = Short.parseShort(dateString.substring(matcher.start(4), matcher.end(4)));
    }
}

private TimeInterval() {
}

public TimeInterval add(TimeInterval interval) {
    TimeInterval ret = new TimeInterval();
    ret.milliSeconds = (short) ((interval.milliSeconds + milliSeconds)%1000);
    int carry = (interval.milliSeconds + milliSeconds)/1000;
    ret.seconds = (short) ((interval.seconds + seconds)%60 + carry );
    carry =(interval.seconds + seconds)/60;
    ret.minutes = (short) ((interval.minutes + minutes)%60 + carry);
    carry = (interval.minutes + minutes)/60;
    ret.hours = (interval.hours + hours + carry);
    return ret;
}

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

Using this class your program will be like :

TimeInterval time = new TimeInterval("00:00:00.000");

try {
    for (int i = 0; i < 24; i++) {
      time = time.add(new TimeInterval("01:00:00.123"));
    }

    System.out.println(time.toString());
} catch (ParseException e) {
    e.printStackTrace();
}

Altri suggerimenti

Have you thought about using days to represent each set of 24 hours? You could add something in your sumTime method, and have it add days. SimpleDateFormater can use days, maybe this will help:

http://docs.oracle.com/javase/6/docs/api/java/text/SimpleDateFormat.html

java.util.Date is not so strong in this area. See the Joda Time for a library that handles this properly.

I don't have access to an installation just now. The code will be close to this:

DateTimeFormatter dtf = DateTimeFormat.forPattern("HH:mm:ss.SSS");
DateTime start = dtf.parseDateTime(date1);
DateTime end = dtf.parseDateTime(date2);
PeriodFormatter pf = new PeriodFormatterBuilder()
 .printZeroAlways().appendHours().appendSeparator(":")
 .appendMinutes().appendSeparator(":")
 .appendSeconds().appendSeparator(":")
 .appendMillis3Digit().toFormatter();
return pf.print(new Period(start, end, PeriodType.time()));

Have you tried Joda-Time which actually has direct support for this sort of thing?

    PeriodFormatterBuilder builder = new PeriodFormatterBuilder();
    builder.printZeroAlways()
        .minimumPrintedDigits(2)
        .appendHours()
        .appendSeparator(":").appendMinutes()
        .appendSeparator(":").appendSeconds()
        .appendSeparator(".").appendMillis3Digit();

    PeriodFormatter formatter = builder.toFormatter();
    PeriodParser parser = builder.toParser();

    String s1 = "11:00:00.111";
    String s2 = "23:00:00.111";

    MutablePeriod p1 = new MutablePeriod();
    MutablePeriod p2 = new MutablePeriod();
    parser.parseInto(p1, s1, 0, Locale.getDefault());       
    parser.parseInto(p2, s2, 0, Locale.getDefault());       
    p1.add(p2);


    System.out.println(formatter.print(p1));

Prints

34:00:00.222
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top