如何在Java中将毫秒转换为"X分钟,X秒钟"?

630
我想在我的程序中记录用户开始某项任务时的时间,可以使用System.currentTimeMillis()。当用户完成任务后,我将从start变量中减去当前的System.currentTimeMillis(),然后我想以人类可读的格式显示已经过去的时间,例如 "XX小时,XX分钟,XX秒" 或者 "XX分钟,XX秒",因为不太可能需要一个小时的时间。
最佳方法是什么?

5
如果时间超过一个小时,你仍然可以打印出类似于“90分53秒”的内容。 - Peter Lawrey
30个回答

11

我认为最好的方法是:

String.format("%d min, %d sec", 
    TimeUnit.MILLISECONDS.toSeconds(length)/60,
    TimeUnit.MILLISECONDS.toSeconds(length) % 60 );

你可以使用TimeUnit.MILLISECONDS.toMinutes(length)来计算分钟数。 - Amarjit

9

Joda-Time

Using Joda-Time:

DateTime startTime = new DateTime();

// do something

DateTime endTime = new DateTime();
Duration duration = new Duration(startTime, endTime);
Period period = duration.toPeriod().normalizedStandard(PeriodType.time());
System.out.println(PeriodFormat.getDefault().print(period));

1
在最后一行中不需要使用PeriodFormat。只需调用Period::toString即可默认获取ISO 8601 Duration字符串。 - Basil Bourque

9

对于正在寻找 Kotlin 代码的人:

fun converter(millis: Long): String =
        String.format(
            "%02d : %02d : %02d",
            TimeUnit.MILLISECONDS.toHours(millis),
            TimeUnit.MILLISECONDS.toMinutes(millis) - TimeUnit.HOURS.toMinutes(
                TimeUnit.MILLISECONDS.toHours(millis)
            ),
            TimeUnit.MILLISECONDS.toSeconds(millis) - TimeUnit.MINUTES.toSeconds(
                TimeUnit.MILLISECONDS.toMinutes(millis)
            )
        )

示例输出:09:10:26

8
首先,System.currentTimeMillis()Instant.now()并不是计时的理想方法。它们都报告挂钟时间,计算机无法精确知道,并且时间可能会不稳定,包括如果例如NTP守护程序更正系统时间,则可以向后移动。如果您的计时发生在单台计算机上,则应改用System.nanoTime()
其次,从Java 8开始,java.time.Duration 是表示持续时间的最佳方式:
long start = System.nanoTime();
// do things...
long end = System.nanoTime();
Duration duration = Duration.ofNanos(end - start);
System.out.println(duration); // Prints "PT18M19.511627776S"
System.out.printf("%d Hours %d Minutes %d Seconds%n",
        duration.toHours(), duration.toMinutes() % 60, duration.getSeconds() % 60);
// prints "0 Hours 18 Minutes 19 Seconds"

当你在谷歌上搜索“android”时,它是其中的首要结果之一。 - Andrew

6

我的简单计算:

String millisecToTime(int millisec) {
    int sec = millisec/1000;
    int second = sec % 60;
    int minute = sec / 60;
    if (minute >= 60) {
        int hour = minute / 60;
        minute %= 60;
        return hour + ":" + (minute < 10 ? "0" + minute : minute) + ":" + (second < 10 ? "0" + second : second);
    }
    return minute + ":" + (second < 10 ? "0" + second : second);
}

愉快编码 :)


我认为对于这个函数来说long更合适,因为System.currentTimeMillis()返回一个long值。 - aprodan

5

对于API 9以下的Android系统

(String.format("%d hr %d min, %d sec", millis/(1000*60*60), (millis%(1000*60*60))/(1000*60), ((millis%(1000*60*60))%(1000*60))/1000)) 

4

在Java 9中更容易实现:

    Duration elapsedTime = Duration.ofMillis(millisDiff );
    String humanReadableElapsedTime = String.format(
            "%d hours, %d mins, %d seconds",
            elapsedTime.toHours(),
            elapsedTime.toMinutesPart(),
            elapsedTime.toSecondsPart());

这将生成一个类似于0小时,39分钟,9秒的字符串。
如果您想在格式化之前将其舍入到整秒:
    elapsedTime = elapsedTime.plusMillis(500).truncatedTo(ChronoUnit.SECONDS);

为了在小时数为0的情况下省略它们:
    long hours = elapsedTime.toHours();
    String humanReadableElapsedTime;
    if (hours == 0) {
        humanReadableElapsedTime = String.format(
                "%d mins, %d seconds",
                elapsedTime.toMinutesPart(),
                elapsedTime.toSecondsPart());

    } else {
        humanReadableElapsedTime = String.format(
                "%d hours, %d mins, %d seconds",
                hours,
                elapsedTime.toMinutesPart(),
                elapsedTime.toSecondsPart());
    }

现在,我们可以使用例如 39 分钟,9 秒 的时间。
要打印带有前导零的分钟和秒,使它们始终为两位数,只需将 02 插入相关的格式说明符,如下所示:
    String humanReadableElapsedTime = String.format(
            "%d hours, %02d mins, %02d seconds",
            elapsedTime.toHours(),
            elapsedTime.toMinutesPart(),
            elapsedTime.toSecondsPart());

现在我们可以举一个例子,比如0小时,39分钟,09秒

是否有任何格式化方法可以在前面的数字为0时删除小时/分钟/秒?我的意思是,虽然可以使用if else条件实现,但是否存在类似于字符串格式化或类似的东西? - Farid
1
不好意思,@FARID,你需要在那里使用if-else - Ole V.V.
对于Android,您需要(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) - Mostafa Imani
@MostafaImani 它也适用于较低级别的Android。对于Oreo版本(APi级别26)之前的版本,您可以直接使用java.time,使用coreLibraryDesugaring - Ole V.V.

4
对于小时间段(少于一小时),我更喜欢使用:
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);
}

这是一个宝贵的提示,使用Java Formatter API(https://docs.oracle.com/javase/8/docs/api/java/util/Formatter.html)可以实现许多日期和时间的格式化! 您还可以使用以下代码块来获得else条件的结果: System.out.printf("%1$tH:%1$tM:%1$tS%n", millis); 或者 System.out.printf("%1$tT%n", millis); - Jose Tepedino
@JoseTepedino 但你应该知道 %tH 显示0到23小时吗?这意味着例如24小时将显示为 00,25小时为 01…… 对于 %tT 相同的有效 - 天数将被忽略。当然,可以显示天数,但这对我编写此代码时遇到的问题来说有些过头了(回到2011年)[: - ) - user85421
我明白了,那只适用于小于一天(24小时)的时间。谢谢。 - Jose Tepedino

4
    long startTime = System.currentTimeMillis();
    // do your work...
    long endTime=System.currentTimeMillis();
    long diff=endTime-startTime;       
    long hours=TimeUnit.MILLISECONDS.toHours(diff);
    diff=diff-(hours*60*60*1000);
    long min=TimeUnit.MILLISECONDS.toMinutes(diff);
    diff=diff-(min*60*1000);
    long seconds=TimeUnit.MILLISECONDS.toSeconds(diff);
    //hour, min and seconds variables contains the time elapsed on your work

3
第6行的公式是错误的。diff=diff-(hours*60*1000); 应该是 diff=diff-(hours*60*60*1000);。我尝试编辑它,但 StackOverflow 的烦人编辑政策说它没有足够的字符来进行编辑。 - quux00

4

以下是基于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());
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接