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

Posted

技术标签:

【中文标题】如何将毫秒转换为“hh:mm:ss”格式?【英文标题】:How to convert milliseconds to "hh:mm:ss" format? 【发布时间】:2012-02-20 02:08:45 【问题描述】:

我很困惑。在偶然发现this 线程后,我试图弄清楚如何格式化具有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))

【问题讨论】:

3,600,000 毫秒是 3,600 秒、60 分钟或 1 小时。不应该是00:59:59,应该是01:00:00 【参考方案1】:

真的很亲密:

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)));   

您使用 minutes 而不是 hours 将小时转换为毫秒。

顺便说一句,我喜欢你使用 TimeUnit API :)

这是一些测试代码:

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));

仍然对所有魔法值使用TimeUnit API,并提供完全相同的输出。

【讨论】:

阿门,就像你使用 TimeUnit API 的方式一样 :) 重新发明***不是个好主意! Triton Man 的答案是更好的解决方案。 @محمدباقر 但另一个答案使用外部库,而我的代码仅使用核心 JDK。这取决于您的需求 - 例如,您可能无法使用外部库。不过,另一个答案很好。 @Ozuf 添加 .replaceAll("^00:", "").replaceAll("^00:(00:)?", "") 以删除分钟和小时(如果两者都为零)。 @Ozuf 你分别得到"15:00""10:00:23";由于匹配被^锚定到输入的开头,因此只删除了前导零。【参考方案2】:

通用方法相当简单:

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);

【讨论】:

@Javaman59,你的意思是String.format("% 02 d:%02d:%02d", h,m,s) @KarenAnne。这取决于您是否想要,例如“03:59:59”或“3:59:59”。 时间单位为毫秒,需要用秒乘以1000 作者问的是毫秒,而不是秒!【参考方案3】:

如果你使用的是 apache commons:

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

【讨论】:

快捷方式:DurationFormatUtils.formatDurationHMS(timeInMS); @Jorgesys 为什么它们已经过时了? 它们并没有过时。【参考方案4】:

我用过这个:

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

查看类Formatter的描述。

使用 2400 毫秒的输入查看 runnable example。

【讨论】:

它似乎不起作用,我只是通过 100、1000、1200 测试它,它的响应为 05:30:0005:30:01,05:30:01. @CoDe,它适用于您的时区。您必须位于与 UTC 不同的时区。 String.format() 是时区依赖。然而,理想的正确答案应该是时区独立 @CoDe,它显示的时间与您的时区相对应,必须不同于 UTC。 String.format() 是时区依赖。然而,理想的正确答案应该是时区独立【参考方案5】:
// 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 );

您也可以使用新的 DateTime API

     var formatted = DateTimeFormatter.ofPattern("HH:mm:ss.SSS")
            .withZone(ZoneId.of("UTC"))
            .format(Instant.ofEpochMilli(millis));

【讨论】:

这会在超过一天的时间内产生不正确的结果。它将小时数从 23 换回 0,这在这里可能是不可取的。 没有朋友...我认为它仍然可以正常工作。试试今天的日期 SimpleDateFormat sdf = new SimpleDateFormat("hh:mm aa");以防有人想要上午/下午的 12 小时格式【参考方案6】:
DateFormat df = new SimpleDateFormat("HH:mm:ss");
String formatted = df.format(aDateObject);

【讨论】:

与***.com/questions/9027317/… 相同的答案,持续时间超过 1 天 它还取决于时区,这意味着在不同时区运行时结果会有所不同。【参考方案7】:

这对我有用,使用 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"
            
        
    

【讨论】:

非常适合我。这应该是最好的答案,因为它处理零小时【参考方案8】:

4 种实现的测试结果

必须对大量数据进行大量格式化,需要最佳性能,因此以下是(令人惊讶的)结果:

for (int i = 0; i

持续时间:

combinationFormatter:196毫秒 格式持续时间:272毫秒 apacheFormat: 754 毫秒

格式时间单位: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(); 
 

【讨论】:

这样的指标有多可靠?我从来没有真正理解过这个过程。 在我连续创建了数千个对象的情况下,我认为这个测试非常有用。好的,不只是设置一些字符串,而是创建一个具有格式化字符串的字段的对象。 @marius 你很麻烦地使用StringBuilder 然后错误地使用“0”+数字类型的“破坏”它。 @mre JVM 的 GC 非常擅长分配和收集大量短期对象,不用担心。我选择了String.format 没有要处理的前导零逻辑。【参考方案9】:

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,这是现代类的后向端口(JSR 310 的 ThreeTen;请参阅底部的链接)。 在(较旧的)Android 上使用 ThreeTen Backport 的 Android 版本。它被称为 ThreeTenABP。并确保从 org.threeten.bp 导入日期和时间类以及子包。

链接

Oracle tutorial: Date Time 解释如何使用java.time。 Java Specification Request (JSR) 310,其中首次描述了 java.time。 ThreeTen Backport project,java.time 到 Java 6 和 7(JSR-310 的 ThreeTen)的反向移植。 ThreeTenABP,Android 版 ThreeTen Backport Question: How to use ThreeTenABP in Android Project,解释得很透彻。

【讨论】:

【参考方案10】:

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

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);

【讨论】:

【参考方案11】:

按照 Bohemian 的回答,我们不需要使用 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 只需使用millisLeft%1000【参考方案12】:
        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 毫秒

00:10:15.605

【讨论】:

【参考方案13】:
 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

【讨论】:

答案取决于时区,这意味着在不同时区运行时结果会有所不同。【参考方案14】:

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

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;
    

【讨论】:

我赞成这个解决方案。只需在 sec 和 mls 之间添加一个点。而且我不知道为什么在 Java 中时间和日期处理如此困难。最常用的函数应该已经可用并且是类的一部分。【参考方案15】:

我尝试如第一个答案所示。它有效,但减号让我感到困惑。我的 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])

【讨论】:

【参考方案16】:

对于科特林

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 是毫秒

【讨论】:

【参考方案17】:

嗯,你可以试试这样的:

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;  
   

将毫秒转换为时间值

【讨论】:

【参考方案18】:

在 Kotlin 中:

fun FUNCTION_NAME(milliSeconds: Long): String 
    val s: Long = milliSeconds / 1000 % 60

    val m: Long = milliSeconds / (1000*60) % 60

    val h: Long = milliSeconds / (1000*60*60) % 24

    return String.format("%02d:%02d:%02d", h, m, s)

【讨论】:

这个问题用JAVA问,请用Java回答。 这个问题已有 9 年历史,Kotlin 是“旨在与 Java 完全互操作的”,所以我认为这个问题可以扩展以允许在同一领域使用新技术。像这样的评论会让人们远离 SO。【参考方案19】:

在 kotlin 中

private fun stringForTime(timeMs: Int): String 
    val totalSeconds = timeMs / 1000
    val seconds = totalSeconds % 60
    val minutes = totalSeconds / 60 % 60
    val hours = totalSeconds / 3600
    return if (hours > 0) 
        "%d:%02d:%02d".format(hours, minutes, seconds)
     else 
        "%02d:%02d".format(minutes, seconds)
    

在 Java 中

private String stringForTime(int timeMs) 
    int totalSeconds = timeMs / 1000;
    int seconds = totalSeconds % 60;
    int minutes = totalSeconds / 60 % 60;
    int hours = totalSeconds / 3600;
    return hours > 0 ? String.format(Locale.getDefault(),
            "%d:%02d:%02d",
            hours,
            minutes,
            seconds) :
            String.format(Locale.getDefault(),
                    "%02d:%02d",
                    minutes,
                    seconds);

【讨论】:

以上是关于如何将毫秒转换为“hh:mm:ss”格式?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Oracle 中将毫秒转换为 hh mm ss 格式

如何将毫秒更改为 yyyy-MM-dd HH:mm:ss 格式的日期对象 [重复]

C# 以 hh:mm:ss 格式显示毫秒

如何将 HH:mm:ss.SSS 转换为毫秒?

仅将 HH:MM:SS 格式的时间转换为秒?

如何将日期时间从 PowerShell 输出转换为 yyyy-MM-dd HH:mm:ss 格式