【问题标题】:How to convert milliseconds to "hh:mm:ss" format?如何将毫秒转换为“hh:mm:ss”格式?
【发布时间】: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。

标签: java time-format countdowntimer


【解决方案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:00 , 05: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);

【讨论】:

【解决方案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 更优雅且不易出错。

我使用的 toMinutesPart 和 toSecondsPart 方法是在 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 导入日期和时间类以及子包。

链接

【讨论】:

    【解决方案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);
              }
              

              【讨论】:

                猜你喜欢
                • 2022-11-28
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2021-05-09
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2014-12-18
                相关资源
                最近更新 更多