我想使用System.currentTimeMillis()记录用户在程序中开始某项操作时的时间。当他完成时,我将从start变量中减去当前的System.currentTimeMillis(),并且我希望使用人类可读的格式显示他们所经过的时间,例如“XX小时,XX分钟,XX秒”,甚至“XX分钟,XX秒”,因为它不太可能花费某人一个小时。

最好的方法是什么?


当前回答

最短的解决方案:

这可能是最短的一个,也涉及到时区。

System.out.printf("%tT", millis-TimeZone.getDefault().getRawOffset());

输出例如:

00:18:32

解释:

%tT是24小时时钟格式为%tH:%tM:%tS的时间。

%tT也接受长时间作为输入,因此不需要创建Date。Printf()将简单地以毫秒为单位打印指定的时间,但在当前时区中,因此我们必须减去当前时区的原始偏移量,以便0毫秒将是0小时,而不是当前时区的时间偏移值。

注意#1:如果你需要一个字符串形式的结果,你可以这样得到它:

String t = String.format("%tT", millis-TimeZone.getDefault().getRawOffset());

注意#2:只有当millis小于一天时,才会给出正确的结果,因为一天部分不包括在输出中。

其他回答

下面是一个基于Brent Nash的答案,希望有帮助!

public static String getDurationBreakdown(long millis)
{
    String[] units = {" Days ", " Hours ", " Minutes ", " Seconds "};
    Long[] values = new Long[units.length];
    if(millis < 0)
    {
        throw new IllegalArgumentException("Duration must be greater than zero!");
    }

    values[0] = TimeUnit.MILLISECONDS.toDays(millis);
    millis -= TimeUnit.DAYS.toMillis(values[0]);
    values[1] = TimeUnit.MILLISECONDS.toHours(millis);
    millis -= TimeUnit.HOURS.toMillis(values[1]);
    values[2] = TimeUnit.MILLISECONDS.toMinutes(millis);
    millis -= TimeUnit.MINUTES.toMillis(values[2]);
    values[3] = TimeUnit.MILLISECONDS.toSeconds(millis);

    StringBuilder sb = new StringBuilder(64);
    boolean startPrinting = false;
    for(int i = 0; i < units.length; i++){
        if( !startPrinting && values[i] != 0)
            startPrinting = true;
        if(startPrinting){
            sb.append(values[i]);
            sb.append(units[i]);
        }
    }

    return(sb.toString());
}

最短的解决方案:

这可能是最短的一个,也涉及到时区。

System.out.printf("%tT", millis-TimeZone.getDefault().getRawOffset());

输出例如:

00:18:32

解释:

%tT是24小时时钟格式为%tH:%tM:%tS的时间。

%tT也接受长时间作为输入,因此不需要创建Date。Printf()将简单地以毫秒为单位打印指定的时间,但在当前时区中,因此我们必须减去当前时区的原始偏移量,以便0毫秒将是0小时,而不是当前时区的时间偏移值。

注意#1:如果你需要一个字符串形式的结果,你可以这样得到它:

String t = String.format("%tT", millis-TimeZone.getDefault().getRawOffset());

注意#2:只有当millis小于一天时,才会给出正确的结果,因为一天部分不包括在输出中。

我修改了@MyKuLLSKI的回答,增加了多元化支持。我去掉了几秒,因为我不需要它们,如果你需要的话,可以重新添加。

public static String intervalToHumanReadableTime(int intervalMins) {

    if(intervalMins <= 0) {
        return "0";
    } else {

        long intervalMs = intervalMins * 60 * 1000;

        long days = TimeUnit.MILLISECONDS.toDays(intervalMs);
        intervalMs -= TimeUnit.DAYS.toMillis(days);
        long hours = TimeUnit.MILLISECONDS.toHours(intervalMs);
        intervalMs -= TimeUnit.HOURS.toMillis(hours);
        long minutes = TimeUnit.MILLISECONDS.toMinutes(intervalMs);

        StringBuilder sb = new StringBuilder(12);

        if (days >= 1) {
            sb.append(days).append(" day").append(pluralize(days)).append(", ");
        }

        if (hours >= 1) {
            sb.append(hours).append(" hour").append(pluralize(hours)).append(", ");
        }

        if (minutes >= 1) {
            sb.append(minutes).append(" minute").append(pluralize(minutes));
        } else {
            sb.delete(sb.length()-2, sb.length()-1);
        }

        return(sb.toString());          

    }

}

public static String pluralize(long val) {
    return (Math.round(val) > 1 ? "s" : "");
}

对于一小时以内的小时间,我更喜欢:

long millis = ...

System.out.printf("%1$TM:%1$TS", millis);
// or
String str = String.format("%1$TM:%1$TS", millis);

对于较长的间隔:

private static final long HOUR = TimeUnit.HOURS.toMillis(1);
...
if (millis < HOUR) {
    System.out.printf("%1$TM:%1$TS%n", millis);
} else {
    System.out.printf("%d:%2$TM:%2$TS%n", millis / HOUR, millis % HOUR);
}

基于@siddhadev的回答,我写了一个将毫秒转换为格式化字符串的函数:

   /**
     * Convert a millisecond duration to a string format
     * 
     * @param millis A duration to convert to a string form
     * @return A string of the form "X Days Y Hours Z Minutes A Seconds".
     */
    public static String getDurationBreakdown(long millis) {
        if(millis < 0) {
            throw new IllegalArgumentException("Duration must be greater than zero!");
        }

        long days = TimeUnit.MILLISECONDS.toDays(millis);
        millis -= TimeUnit.DAYS.toMillis(days);
        long hours = TimeUnit.MILLISECONDS.toHours(millis);
        millis -= TimeUnit.HOURS.toMillis(hours);
        long minutes = TimeUnit.MILLISECONDS.toMinutes(millis);
        millis -= TimeUnit.MINUTES.toMillis(minutes);
        long seconds = TimeUnit.MILLISECONDS.toSeconds(millis);

        StringBuilder sb = new StringBuilder(64);
        sb.append(days);
        sb.append(" Days ");
        sb.append(hours);
        sb.append(" Hours ");
        sb.append(minutes);
        sb.append(" Minutes ");
        sb.append(seconds);
        sb.append(" Seconds");

        return(sb.toString());
    }