如何将毫秒转换为“ hh:mm:ss”格式?


184

我很困惑。绊倒这个线程后,我试图找出如何格式化具有格式的倒数计时器hh:mm:ss

这是我的尝试-

//hh:mm:ss
String.format("%02d:%02d:%02d", 
    TimeUnit.MILLISECONDS.toHours(millis),
    TimeUnit.MILLISECONDS.toMinutes(millis) - 
    TimeUnit.MINUTES.toMinutes(TimeUnit.MILLISECONDS.toHours(millis)),
    TimeUnit.MILLISECONDS.toSeconds(millis) - 
    TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(millis)));   

因此,当我尝试类似的值时3600000ms,我得到01:59:00,这是错误的,因为它应该是01:00:00。显然我的逻辑有问题,但是目前,我看不出它是什么!

有人可以帮忙吗?

编辑-

解决它。这是格式化毫秒hh:mm:ss格式的正确方法-

//hh:mm:ss
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))));

问题是这样TimeUnit.MINUTES.toMinutes(TimeUnit.MILLISECONDS.toHours(millis))。应该是这个TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(millis))


1
3,600,000毫秒是3,600秒或60分钟或1小时。应该不应该00:59:59,应该这样01:00:00
Borealid 2012年

Answers:


354

真的很亲密:

String.format("%02d:%02d:%02d", 
TimeUnit.MILLISECONDS.toHours(millis),
TimeUnit.MILLISECONDS.toMinutes(millis) -  
TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(millis)), // The change is in this line
TimeUnit.MILLISECONDS.toSeconds(millis) - 
TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(millis)));   

您正在使用分钟而不是hours将小时数转换为毫秒。

顺便说一句,我喜欢您对TimeUnitAPI 的使用:)

这是一些测试代码:

public static void main(String[] args) throws ParseException {
    long millis = 3600000;
    String hms = 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)));
    System.out.println(hms);
}

输出:

01:00:00

我意识到上面的代码可以通过使用模数除法而不是减法来大大简化:

String hms = String.format("%02d:%02d:%02d", TimeUnit.MILLISECONDS.toHours(millis),
    TimeUnit.MILLISECONDS.toMinutes(millis) % TimeUnit.HOURS.toMinutes(1),
    TimeUnit.MILLISECONDS.toSeconds(millis) % TimeUnit.MINUTES.toSeconds(1));

仍将TimeUnitAPI用于所有魔术值,并提供完全相同的输出。


2
阿们,就像您使用TimeUnit API的方式一样:)
Dheeraj Bhaskar 2013年

2
重新发明轮子不是一个好主意!Triton Man的答案是更好的解决方案。
محمدباقر

5
@محمدباقر但是另一个答案使用一个外部库,而我的代码仅使用核心JDK。这取决于您的需求-例如,您可能无法使用外部库。另一个答案是好的。
波希米亚

2
@Ozuf添加.replaceAll("^00:", "").replaceAll("^00:(00:)?", "")删除分钟以及小时(如果两者均为零)。
波希米亚

2
@Ozuf 分别得到"15:00""10:00:23";由于匹配被锚定为输入的开头,因此仅删除了前导^
波希米亚

77

通用方法非常简单:

public static String convertSecondsToHMmSs(long seconds) {
    long s = seconds % 60;
    long m = (seconds / 60) % 60;
    long h = (seconds / (60 * 60)) % 24;
    return String.format("%d:%02d:%02d", h,m,s);
}

1
@ Javaman59,您的意思是String.format("% 02 d:%02d:%02d", h,m,s)吗?
卡伦·安妮(KarenAnne)2013年

2
@KarenAnne。这取决于您是否想要例如“ 03:59:59”或“ 3:59:59”。
斯蒂芬·霍斯金

2
时间以毫秒为单位,您需要将秒数乘以1000
Apurva'3

5
作者问的是毫秒,而不是秒!
user924

59

如果您使用的是Apache Commons:

DurationFormatUtils.formatDuration(timeInMS, "HH:mm:ss,SSS");

4
捷径:DurationFormatUtils.formatDurationHMS(timeInMS);
Aroniaina

@Jorgesys为什么它们已过时?
Piovezan

他们不是过时的。
Triton Man

26

我用这个:

String.format("%1$tH:%1$tM:%1$tS.%1$tL", millis);

请参阅类Formatter的描述。

请参见使用2400 ms输入的可运行示例


似乎不起作用,我只是通过pass 100、1000、1200 对其进行了测试,它的响应时间为05 : 30 : 00,05 : 30 : 01,05 : 30:01
CoDe17年

2
@CoDe,它适用于您的时区。您所处的时区必须与UTC不同。 String.format()是时区相关。但是,理想的正确答案应该与时区无关
德里克·马哈

@CoDe,它显示的时间与您的时区相对应,必须与UTC不同。String.format()是时区相关。但是,理想的正确答案应该与时区无关
德里克·马哈

25
// New date object from millis
Date date = new Date(millis);
// formattter 
SimpleDateFormat formatter= new SimpleDateFormat("HH:mm:ss.SSS");
formatter.setTimeZone(TimeZone.getTimeZone("UTC"));
// Pass date object
String formatted = formatter.format(date );

请参见使用1200 ms输入的可运行示例


3
超过一天的时间将产生错误的结果。它将小时数从23换回0,这在这里可能是不希望的。
Kenster 2014年

没有朋友...我认为它仍然可以正常工作。尝试今天的约会
Vinay Lodha 2014年

1
SimpleDateFormat sdf = new SimpleDateFormat(“ hh:mm aa”); 如果有人想要12小时制的am / pm
Ajji,


10

4种实现的测试结果

必须对海量数据进行大量格式化,需要最好的性能,所以这是(令人惊讶的)结果:

for(int i = 0; i <1000000; i ++){FUNCTION_CALL}

持续时间:

  • 组合格式:196毫秒
  • formatDuration:272米利斯
  • apache格式:754毫秒
  • formatTimeUnit:2216毫秒

    public static String apacheFormat(long millis) throws ParseException {
        return DurationFormatUtils.formatDuration(millis, "HH:mm:ss");
    }
    
    public static String formatTimeUnit(long millis) throws ParseException {
    String formatted = 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)));
        return formatted;
    }
    
    public static String formatDuration(final long millis) {
        long seconds = (millis / 1000) % 60;
        long minutes = (millis / (1000 * 60)) % 60;
        long hours = millis / (1000 * 60 * 60);
    
        StringBuilder b = new StringBuilder();
        b.append(hours == 0 ? "00" : hours < 10 ? String.valueOf("0" + hours) : 
        String.valueOf(hours));
        b.append(":");
        b.append(minutes == 0 ? "00" : minutes < 10 ? String.valueOf("0" + minutes) :     
        String.valueOf(minutes));
        b.append(":");
        b.append(seconds == 0 ? "00" : seconds < 10 ? String.valueOf("0" + seconds) : 
        String.valueOf(seconds));
        return b.toString();
    }
    
    public static String combinationFormatter(final long millis) {
        long seconds = TimeUnit.MILLISECONDS.toSeconds(millis)
                - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(millis));
        long minutes = TimeUnit.MILLISECONDS.toMinutes(millis)
                - TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(millis));
        long hours = TimeUnit.MILLISECONDS.toHours(millis);
    
        StringBuilder b = new StringBuilder();
        b.append(hours == 0 ? "00" : hours < 10 ? String.valueOf("0" + hours) : 
        String.valueOf(hours));
        b.append(":");
        b.append(minutes == 0 ? "00" : minutes < 10 ? String.valueOf("0" + minutes) : 
        String.valueOf(minutes));
            b.append(":");
        b.append(seconds == 0 ? "00" : seconds < 10 ? String.valueOf("0" + seconds) : 
        String.valueOf(seconds));
        return b.toString(); 
     }

这些指标的可靠性如何?我从来没有真正了解过这个过程。
mre 2014年

在连续创建数千个对象的情况下,我认为此测试非常有用。可以不仅设置一些字符串,还可以创建具有一个字段的格式化字符串的对象。
MariusA 2014年

@marius麻烦您使用,StringBuilder然后犯下使用“ 0” +数字类型的“废墟”的错误。@mre JVM的GC非常擅长分配和收集许多短期对象,而无需担心。我String.format没有要处理的前导零逻辑。
escape-llc

6

按照波希米亚的答案,我们不需要使用TimeUnit来查找已知值。更好的代码将是

String hms = String.format("%02d:%02d:%02d", millisLeft/(3600*1000),
                    millisLeft/(60*1000) % 60,
                    millisLeft/1000 % 60);

希望能帮助到你


最喜欢您的答案!只是简单的数学。顺便说一下我的情况下,我加入了毫秒到最后millisLeft%1000/10,所以我们得到的格式hour:minutes:seconds:milliseconds
黎光维战

@LêQuangDuy我需要3位数的毫秒,例如01:24:51,123,但您最后要砍3怎么办?
naanu

@naanu只需使用millisLeft%1000
黎光维战

6
 public String millsToDateFormat(long mills) {

    Date date = new Date(mills);
    DateFormat formatter = new SimpleDateFormat("HH:mm:ss");
    String dateFormatted = formatter.format(date);
    return dateFormatted; //note that it will give you the time in GMT+0
}

答案取决于时区,这意味着在不同时区运行时结果将有所不同。
德里克·马哈

6

这对我有用,与kotlin

fun formatToDigitalClock(miliSeconds: Long): String {
        val hours = TimeUnit.MILLISECONDS.toHours(miliSeconds).toInt() % 24
        val minutes = TimeUnit.MILLISECONDS.toMinutes(miliSeconds).toInt() % 60
        val seconds = TimeUnit.MILLISECONDS.toSeconds(miliSeconds).toInt() % 60
        return when {
            hours > 0 -> String.format("%d:%02d:%02d", hours, minutes, seconds)
            minutes > 0 -> String.format("%02d:%02d", minutes, seconds)
            seconds > 0 -> String.format("00:%02d", seconds)
            else -> {
                "00:00"
            }
        }
    }

为我完美地工作。这应该是最好的答案,因为它处理的是零时
vNext

6

Java 9

    Duration timeLeft = Duration.ofMillis(3600000);
    String hhmmss = String.format("%02d:%02d:%02d", 
            timeLeft.toHours(), timeLeft.toMinutesPart(), timeLeft.toSecondsPart());
    System.out.println(hhmmss);

打印:

01:00:00

您让库方法为您完成涉及的转换是对的。java.time,现代的Java日期和时间API,或更准确地说,与相比,其Duration类更优雅,更不易出错TimeUnit

我使用的toMinutesParttoSecondsPart方法是在Java 9中引入的。

Java 6、7和8

    long hours = timeLeft.toHours();
    timeLeft = timeLeft.minusHours(hours);
    long minutes = timeLeft.toMinutes();
    timeLeft = timeLeft.minusMinutes(minutes);
    long seconds = timeLeft.toSeconds();
    String hhmmss = String.format("%02d:%02d:%02d", hours, minutes, seconds);
    System.out.println(hhmmss);

输出与上面相同。

问题:在Java 6和7中如何工作?

  • 在Java 8和更高版本以及较新的Android设备中(有人告诉我API级别为26)java.time是内置的。
  • 在Java 6和7中,获取ThreeTen Backport,这是现代类的backport(JSR 310的ThreeTen;请参见底部的链接)。
  • 在较旧的Android上,请使用Android版本的ThreeTen Backport。它称为ThreeTenABP。并确保您导入org.threeten.bp带有子包的日期和时间类。

链接


5

下面的代码以两种方式进行转换

23:59:58:999至86398999

然后

86398999至23:59:58:999


import java.util.concurrent.TimeUnit;

public class TimeUtility {

    public static void main(String[] args) {

        long currentDateTime = System.currentTimeMillis();

        String strTest = "23:59:58:999";
        System.out.println(strTest);

        long l = strToMilli(strTest);
        System.out.println(l);
        l += 1;
        String str = milliToString(l);
        System.out.println(str);
    }

    /**
     * convert a time string into the equivalent long milliseconds
     *
     * @param strTime string fomratted as HH:MM:SS:MSMS i.e. "23:59:59:999"
     * @return long integer like 86399999
     */
    public static long strToMilli(String strTime) {
        long retVal = 0;
        String hour = strTime.substring(0, 2);
        String min = strTime.substring(3, 5);
        String sec = strTime.substring(6, 8);
        String milli = strTime.substring(9, 12);
        int h = Integer.parseInt(hour);
        int m = Integer.parseInt(min);
        int s = Integer.parseInt(sec);
        int ms = Integer.parseInt(milli);

        String strDebug = String.format("%02d:%02d:%02d:%03d", h, m, s, ms);
        //System.out.println(strDebug);
        long lH = h * 60 * 60 * 1000;
        long lM = m * 60 * 1000;
        long lS = s * 1000;

        retVal = lH + lM + lS + ms;
        return retVal;
    }

    /**
     * convert time in milliseconds to the corresponding string, in case of day
     * rollover start from scratch 23:59:59:999 + 1 = 00:00:00:000
     *
     * @param millis the number of milliseconds corresponding to tim i.e.
     *               34137999 that can be obtained as follows;
     *               <p>
     *               long lH = h * 60 * 60 * 1000; //hour to milli
     *               <p>
     *               long lM = m * 60 * 1000; // minute to milli
     *               <p>
     *               long lS = s * 1000; //seconds to milli
     *               <p>
     *               millis = lH + lM + lS + ms;
     * @return a string formatted as HH:MM:SS:MSMS i.e. "23:59:59:999"
     */
    private static String milliToString(long millis) {

        long hrs = TimeUnit.MILLISECONDS.toHours(millis) % 24;
        long min = TimeUnit.MILLISECONDS.toMinutes(millis) % 60;
        long sec = TimeUnit.MILLISECONDS.toSeconds(millis) % 60;
        //millis = millis - (hrs * 60 * 60 * 1000); //alternative way
        //millis = millis - (min * 60 * 1000);
        //millis = millis - (sec * 1000);
        //long mls = millis ;
        long mls = millis % 1000;
        String toRet = String.format("%02d:%02d:%02d:%03d", hrs, min, sec, mls);
        //System.out.println(toRet);
        return toRet;
    }
}

我赞成这个解决方案。只需在秒和毫升之间插入一个点。而且我不知道为什么在Java中很难处理时间和日期。最常用的功能应该已经可用,并且是该类的一部分。
Baruch Atta,

5
        String string = String.format("%02d:%02d:%02d.%03d",
            TimeUnit.MILLISECONDS.toHours(millisecend), TimeUnit.MILLISECONDS.toMinutes(millisecend) - TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(millisecend)),
            TimeUnit.MILLISECONDS.toSeconds(millisecend) - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(millisecend)), millisecend - TimeUnit.SECONDS.toMillis(TimeUnit.MILLISECONDS.toSeconds(millisecend)));

格式:00:00:00.000

示例:615605 Millisecend

00:10:15.605


5

标记为正确的答案有一点错误,

String myTime = String.format("%02d:%02d:%02d",
            TimeUnit.MILLISECONDS.toHours(millis),
            TimeUnit.MILLISECONDS.toMinutes(millis) -
                    TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(millis)), // The change is in this line
            TimeUnit.MILLISECONDS.toSeconds(millis) -
                    TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(millis)));

例如,这是我得到的价值的一个例子:

417474:44:19

这是获得正确格式的解决方案:

String myTime =  String.format("%02d:%02d:%02d",
                //Hours
                TimeUnit.MILLISECONDS.toHours(millis) -
                        TimeUnit.DAYS.toHours(TimeUnit.MILLISECONDS.toDays(millis)),
                //Minutes
                TimeUnit.MILLISECONDS.toMinutes(millis) -
                        TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(millis)),
                //Seconds
                TimeUnit.MILLISECONDS.toSeconds(millis) -
                        TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(millis)));

结果得到正确的格式:

18:44:19

获取格式的另一种选择hh:mm:ss是:

   Date myDate = new Date(timeinMillis);
   SimpleDateFormat formatter = new SimpleDateFormat("HH:mm:ss");
   String myTime = formatter.format(myDate);

4

我尝试了如第一个答案所示。它可以工作,但是让我感到困惑。我对Groovy的回答:

import static java.util.concurrent.TimeUnit.*

...

private static String formatElapsedTime(long millis) {

    int hrs = MILLISECONDS.toHours(millis) % 24
    int min = MILLISECONDS.toMinutes(millis) % 60
    int sec = MILLISECONDS.toSeconds(millis) % 60
    int mls = millis % 1000

    sprintf( '%02d:%02d:%02d (%03d)', [hrs, min, sec, mls])
}

3

对于科特林

val hours = String.format("%02d", TimeUnit.MILLISECONDS.toHours(milSecs))
val minutes = String.format("%02d",
                        TimeUnit.MILLISECONDS.toMinutes(milSecs) - TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(milSecs)))
val seconds = String.format("%02d",
                        TimeUnit.MILLISECONDS.toSeconds(milSecs) - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(milSecs)))

其中,milSecs单位是毫秒


1

好吧,你可以尝试这样的事情:

public String getElapsedTimeHoursMinutesSecondsString() {       
     long elapsedTime = getElapsedTime();  
     String format = String.format("%%0%dd", 2);  
     elapsedTime = elapsedTime / 1000;  
     String seconds = String.format(format, elapsedTime % 60);  
     String minutes = String.format(format, (elapsedTime % 3600) / 60);  
     String hours = String.format(format, elapsedTime / 3600);  
     String time =  hours + ":" + minutes + ":" + seconds;  
     return time;  
 }  

将毫秒转换为时间值

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.