How to format an elapsed time interval in hh:mm:ss

2019-01-17 19:46发布

I'm making a stop watch where I'm using Java's SimpleDateFormat to convert the number of milliseconds into a nice "hh:mm:ss:SSS" format. The problem is the hours field always has some random number in it. Here's the code I'm using:

public static String formatTime(long millis) {
    SimpleDateFormat sdf = new SimpleDateFormat("hh:mm:ss.SSS");

    String strDate = sdf.format(millis);
    return strDate;
}

If I take off the hh part then it works fine. Otherwise in the hh part it'll display something random like "07" even if the argument passed in (number of milliseconds) is zero.

I don't know much about the SimpleDateFormat class though. Thanks for any help.

12条回答
smile是对你的礼貌
2楼-- · 2019-01-17 19:56

Why not this ?

public static String GetFormattedInterval(final long ms) {
    long millis = ms % 1000;
    long x = ms / 1000;
    long seconds = x % 60;
    x /= 60;
    long minutes = x % 60;
    x /= 60;
    long hours = x % 24;

    return String.format("%02d:%02d:%02d.%03d", hours, minutes, seconds, millis);
}
查看更多
爱情/是我丢掉的垃圾
3楼-- · 2019-01-17 20:00

Variant: Up to 24 hours

Simple formatting for elapsed time less than 24h. Over 24h the code will only display the hours within the next day and won't add the elapsed day to the hours.

public static String formatElapsedTime(long milliseconds) {

    SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss.SSS");
    sdf.setTimeZone(TimeZone.getTimeZone("UTC"));

    return sdf.format(milliseconds);
}

Missing features in sample code:

  • Eliminate the timezone with "UTC"
  • Use the 24h format "HH"

Variant: Over 24 hours

public static String formatElapsedTimeOver24h(long milliseconds) {

    // Compiler will take care of constant arithmetics
    if (24 * 60 * 60 * 1000 > milliseconds) {
        SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss.SSS");
        sdf.setTimeZone(TimeZone.getTimeZone("UTC"));

        return sdf.format(milliseconds);

    } else {
        SimpleDateFormat sdf = new SimpleDateFormat(":mm:ss.SSS");
        sdf.setTimeZone(TimeZone.getTimeZone("UTC"));

        // Keep long data type
        // Compiler will take care of constant arithmetics
        long hours = milliseconds / (60L * 60L * 1000L);

        return hours + sdf.format(milliseconds);
    }
}
查看更多
老娘就宠你
4楼-- · 2019-01-17 20:04

Using a plain Java Calendar for intervals up to one day (24 hours) see my answer to the question: How to format time intervals in Java?

查看更多
女痞
5楼-- · 2019-01-17 20:04

This one actually works, but it seems like I'm tweaking the intent of the method :-).

public static String formatTime(long millis) {
    SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss.SSS");

    String strDate = sdf.format(millis - 3600000);
    return strDate;
}

For those of you who really knows how this works you'll probably find some caveats.

查看更多
女痞
6楼-- · 2019-01-17 20:07

Support for what you want to do is built in to the latest JDKs with a little known class called TimeUnit.

What you want to use is java.util.concurrent.TimeUnit to work with intervals.

SimpleDateFormat does just what it sounds like it does, it formats instances of java.util.Date, or in your case it converts the long value into the context of a java.util.Date and it doesn't know what to do with intervals which is what you apparently are working with.

You can easily do this without having to resort to external libraries like JodaTime.

import java.util.concurrent.TimeUnit;

public class Main
{        
    private static String formatInterval(final long l)
    {
        final long hr = TimeUnit.MILLISECONDS.toHours(l);
        final long min = TimeUnit.MILLISECONDS.toMinutes(l - TimeUnit.HOURS.toMillis(hr));
        final long sec = TimeUnit.MILLISECONDS.toSeconds(l - TimeUnit.HOURS.toMillis(hr) - TimeUnit.MINUTES.toMillis(min));
        final long ms = TimeUnit.MILLISECONDS.toMillis(l - TimeUnit.HOURS.toMillis(hr) - TimeUnit.MINUTES.toMillis(min) - TimeUnit.SECONDS.toMillis(sec));
        return String.format("%02d:%02d:%02d.%03d", hr, min, sec, ms);
    }

    public static void main(final String[] args)
    {
        System.out.println(formatInterval(Long.parseLong(args[0])));
    }
}

The output will be formatted something like this

13:00:00.000
查看更多
ゆ 、 Hurt°
7楼-- · 2019-01-17 20:08

Reviewing the other answers, I came up with this function...

public static String formatInterval(final long interval, boolean millisecs )
{
    final long hr = TimeUnit.MILLISECONDS.toHours(interval);
    final long min = TimeUnit.MILLISECONDS.toMinutes(interval) %60;
    final long sec = TimeUnit.MILLISECONDS.toSeconds(interval) %60;
    final long ms = TimeUnit.MILLISECONDS.toMillis(interval) %1000;
    if( millisecs ) {
        return String.format("%02d:%02d:%02d.%03d", hr, min, sec, ms);
    } else {
        return String.format("%02d:%02d:%02d", hr, min, sec );
    }
}
查看更多
登录 后发表回答