简体   繁体   中英

calculate elapsed time and display it in Java

There seems to be no easy answer in stackoverflow for this problem. I simply want to get the difference between two Calendar instances and display in HH:mm:ss.SSS

So far, I have

SimpleDateFormat dateFormat = new                      
  SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");           
  Calendar start = Calendar.getInstance();               
  say("start time:"+dateFormat.format(start.getTime())); 

and

 Calendar ending = Calendar.getInstance();              
  say("ending time:"+dateFormat.format(ending.getTime()));
 long milli = ending.getTime().getTime()      
             - start.getTime().getTime();     
 long sec = milli / 1000; // millisec to sec  
 say("elapsed time: " + sec + "." + milli );  

which does work to display the two times.

 start time: 2018-03-02 15:44:41.194  
*** program runs ***
 ending time:2018-03-02 15:44:41.198 
 elapsed time: 0.4                   

But shouldn't it be saying 0.004 seconds?

And PLEASE no JodaTime answers. This shop does not support that.

    Instant start = Instant.now();

And

    Instant end = Instant.now();
    long milli = ChronoUnit.MILLIS.between(start, end);
    System.out.format(Locale.ENGLISH, "elapsed time: %.3f%n", milli / 1000.0);

On my computer this printed

elapsed time: 0.004

Formatting with String.format or System.out.format() also works with your way of measuring the milliseconds, of course.

Using Java 9 you can (at least on some computers) have more decimals if you want:

    System.out.println("elapsed time: " 
            +  ChronoUnit.NANOS.between(start, end) / (double) TimeUnit.SECONDS.toNanos(1));

I got

elapsed time: 0.003739

I wrote a little function for you, it returns a number as a string filled with as many "0" as you want.

public String getStringNumber(long number, int displaySize) {
    String str = new String();
    int length = String.valueOf(number).length();
    while (length++ < displaySize)
        str += "0";
    str += number;
    return str;
}

Now you can just replace in your code

say("elapsed time: " + sec + "." + getStringNumber(milli, 4));

I finally arrived on this solution. It is awkward and not very elegant, but it works.

Calendar ending = Calendar.getInstance();
say("ending time:"+dateFormat.format(ending.getTime()));

long milli = ending.getTime().getTime()
- start.getTime().getTime();

long hrs = TimeUnit.MILLISECONDS.toHours(milli) % 24;
long min = TimeUnit.MILLISECONDS.toMinutes(milli) % 60;
long sec = TimeUnit.MILLISECONDS.toSeconds(milli) % 60;
long mls = milli % 1000;
String elaps = String.format("%02d:%02d:%02d.%03d", hrs,
min, sec, mls);

say("Elapsed time: " + elaps);

Here is the explanation: I convert the two Calendar variables to long, and subtract. Then I format the Long to a string in format hh:mm:ss.SSS which is what I wanted in the first place.

Here is the output

ending time:2018-03-05 15:07:17.923
Elapsed time: 00:01:15.964

Okay, so, simply off the top of my head, without trying to perform anything kind of fancy, you could make use of the Java 8 date/time API, which provides the capability to calculate the different between two points in time.

So, taking your input, and running it through the code below, it outputs

2018-03-02T15:44:41.194
2018-03-02T15:44:41.198
0.004

Now, personally, I'd take the concept and simply create a DurationFormatter which could take a Duration and spit out your required format, but the idea here is to give you a jumping point to start from.

import java.time.Duration;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

public class Test {

    public static void main(String[] args) {
        String startTime = "2018-03-02 15:44:41.194";
        String endTime = "2018-03-02 15:44:41.198";

        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS");

        LocalDateTime startDateTime = LocalDateTime.parse(startTime, formatter);
        LocalDateTime endDateTime = LocalDateTime.parse(endTime, formatter);

        System.out.println(startDateTime);
        System.out.println(endDateTime);

        Duration duration = Duration.between(startDateTime, endDateTime);

        long hours = duration.toHours();
        duration = duration.minusHours(hours);
        long mins = duration.toMinutes();
        duration = duration.minusMinutes(mins);
        long secs = duration.getSeconds();
        duration = duration.minusSeconds(secs);
        long millis = duration.toMillis();

        StringBuilder sb = new StringBuilder(12);
        if (hours > 0) {
            sb.append(pad(hours, 2));
        }
        if (mins == 0 && sb.length() > 0) {
            sb.append(":00");
        } else if (mins > 0) {
            if (hours > 0) {
                sb.append(":");
            }
            sb.append(pad(mins, 2));
        }
        if (secs == 0 & sb.length() > 0) {
            sb.append(":00");
        } else if (secs > 0) {
            if (mins > 0) {
                sb.append(":");
            }
            sb.append(pad(secs, 2));
        }
        if (millis == 0 & sb.length() > 0) {
            sb.append(".00");
        } else if (millis > 0) {
            if (secs > 0 || sb.length() > 0) {
                sb.append(".");
            } else if (sb.length() == 0) {
                sb.append("0.");
            }
            sb.append(pad(millis, 3));
        }

        System.out.println(sb.toString());
    }

    public static String pad(long value, long length) {
        return String.format("%0" + length + "d", value);
    }

}

Now, if we change the input to something like...

String startTime = "2018-03-02 15:44:41.194";
String endTime = "2018-03-08 15:44:41.198";

It outputs

144:00:00.004

Or if we use

String startTime = "2018-03-02 15:44:41.194";
String endTime = "2018-03-08 15:15:41.198";

It outputs

143:31:00.004

Or

String startTime = "2018-03-02 15:44:41.194";
String endTime = "2018-03-08 15:15:50.198";

It outputs

143:31:09.004

Or

2018-03-02T15:44:41.194
2018-03-02T15:50:41.194

It outputs

06:00.00

... to me, this is where it gets weird, technically it's correct (6 mins), but from the format, it's hard to deduce exactly what it means

This is where I might be tempted to use something more like String.format("%02d:%02d:%02d.%04d", hours, mins, secs, millis) which will output 00:06:00.0000 , but that all comes do to you needs. You will need to decide how best to take the raw information and present it based on your needs, but there are a couple of different ideas

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM