Wie konvertiere ich Millisekunden in das Format „hh: mm: ss“?


183

Ich bin verwirrt. Nachdem ich über diesen Thread gestolpert war , versuchte ich herauszufinden, wie man einen Countdown-Timer formatiert, der das Format hatte hh:mm:ss.

Hier ist mein Versuch -

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

Wenn ich also einen Wert wie versuche 3600000ms, bekomme ich 01:59:00, was falsch ist, da es sein sollte 01:00:00. Natürlich stimmt etwas mit meiner Logik nicht, aber im Moment kann ich nicht sehen, was es ist!

Kann jemand helfen?

Bearbeiten -

Behoben. Hier ist der richtige Weg, um Millisekunden zu hh:mm:ssformatieren -

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

Das Problem war das TimeUnit.MINUTES.toMinutes(TimeUnit.MILLISECONDS.toHours(millis)). Es hätte TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(millis))stattdessen so sein sollen.


1
3.600.000 Millisekunden sind 3.600 Sekunden oder 60 Minuten oder 1 Stunde. Es sollte nicht sein 00:59:59, es sollte sein 01:00:00.
Borealid

Antworten:


354

Sie waren wirklich nah:

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

Sie haben Stunden in Millissekunden umgerechnet, indem Sie Minuten anstelle von Stunden verwendet haben .

Übrigens, ich mag Ihre Verwendung der TimeUnitAPI :)

Hier ist ein Testcode:

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

Ausgabe:

01:00:00

Ich habe festgestellt, dass mein Code oben durch die Verwendung einer Moduldivision anstelle einer Subtraktion erheblich vereinfacht werden kann:

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

Verwendet weiterhin die TimeUnitAPI für alle magischen Werte und liefert genau die gleiche Ausgabe.


2
Amen, wie Sie TimeUnit API verwenden :)
Dheeraj Bhaskar

2
Es ist keine gute Idee, das Rad neu zu erfinden! Die Antwort von Triton Man ist eine bessere Lösung.
Freitag,

5
@ محمدباقر Aber die andere Antwort verwendet eine externe Bibliothek, während mein Code nur das Kern-JDK verwendet. Dies hängt von Ihren Anforderungen ab. Beispielsweise können Sie möglicherweise keine externe Bibliothek verwenden. Die andere Antwort ist jedoch gut.
Bohemian

2
@Ozuf füge Minuten .replaceAll("^00:", "")oder .replaceAll("^00:(00:)?", "")Stunden hinzu oder entferne sie, wenn beide Null sind.
Bohemian

2
@Ozuf Sie erhalten "15:00"und "10:00:23"verbunden sind; Es werden nur führende Nullen entfernt, da die Übereinstimmung am Beginn der Eingabe durch verankert ist ^.
Bohemian

77

Die generische Methode hierfür ist ziemlich einfach:

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, meintest du String.format("% 02 d:%02d:%02d", h,m,s) ?
KarenAnne

2
@ KarenAnne. Das hängt davon ab, ob Sie beispielsweise "03:59:59" oder "3:59:59" möchten.
Stephen Hosking

2
Die Zeit ist in Millisekunden, Sie müssen Sekunden mit 1000 multiplizieren
Apurva

5
Autor fragte nach Millisekunden, nicht nach Sekunden!
user924

59

Wenn Sie Apache Commons verwenden:

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

4
DurationFormatUtils.formatDurationHMS(timeInMS);
Abkürzung

@Jorgesys Warum sind sie veraltet?
Piovezan

Sie sind nicht veraltet.
Triton Man

26

Ich habe das benutzt:

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

Siehe Beschreibung der Klasse Formatierer .

Siehe ausführbares Beispiel mit einer Eingabe von 2400 ms.


Es scheint nicht zu funktionieren, ich teste es einfach mit Pass 100, 1000, 1200 und es antwortet als 05:30:00 , 05:30:01 , 05:30:01 .
CoDe

2
@CoDe, es funktioniert für Ihre Zeitzone. Sie müssen sich in einer anderen Zeitzone als UTC befinden. String.format()ist zeitzonenabhängig . Die ideale richtige Antwort sollte jedoch Zeitzone unabhängig .
Derek Mahar

@CoDe zeigt Zeiten an, die Ihrer Zeitzone entsprechen und sich von UTC unterscheiden müssen. String.format()ist zeitzonenabhängig . Die ideale richtige Antwort sollte jedoch Zeitzone unabhängig .
Derek Mahar

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

Siehe ausführbares Beispiel mit einer Eingabe von 1200 ms.


3
Dies würde zu falschen Ergebnissen für Zeiträume von mehr als einem Tag führen. Es würde die Anzahl der Stunden von 23 auf 0 zurückführen, was hier wahrscheinlich nicht wünschenswert ist.
Kenster

Kein Kumpel ... Ich denke, es würde immer noch genauso funktionieren. versuchen Sie es mit dem heutigen Datum
Vinay Lodha

1
SimpleDateFormat sdf = new SimpleDateFormat ("hh: mm aa"); für den Fall, dass jemand im 12-Stunden-Format mit am / pm will
Ajji


10

Testergebnisse für die 4 Implementierungen

Da für große Datenmengen viel formatiert werden musste, war die beste Leistung erforderlich. Hier sind die (überraschenden) Ergebnisse:

für (int i = 0; i <1000000; i ++) {FUNCTION_CALL}

Dauer:

  • KombinationFormater: 196 Millis
  • FormatDauer: 272 Millis
  • apacheFormat: 754 Millis
  • formatTimeUnit: 2216 Millis

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

Wie zuverlässig sind solche Metriken? Ich habe den Prozess nie wirklich verstanden.
Mehr

In meiner Situation, in der einige tausend Objekte nacheinander erstellt werden, ist dieser Test meiner Meinung nach ziemlich nützlich. Okay, nicht nur einige Zeichenfolgen festlegen, sondern Objekte erstellen, deren Feld eine formatierte Zeichenfolge ist.
MariusA

@Marius du hast dir die Mühe gemacht, es zu benutzen, StringBuilderdann hast du den Fehler gemacht, "0" + eine Art "Ruine" zu verwenden. @mre JVMs GC ist extrem gut darin, viele kurzlebige Objekte zuzuweisen und zu sammeln, keine Sorge. Ich ging String.formatohne führende Null-Logik vor.
Flucht-llc

6

Nach Bohemians Antwort müssen wir TimeUnit nicht verwenden, um einen bekannten Wert zu finden. Viel optimaler Code wäre

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

Ich hoffe es hilft


Wie deine Antwort am meisten! Nur einfache Mathematik. Übrigens habe ich in meinem Fall die Millisekunden am Ende hinzugefügt, millisLeft%1000/10damit wir das Format erhaltenhour:minutes:seconds:milliseconds
Lê Quang Duy

@ LêQuangDuy Ich brauche Millisekunden in 3 Ziffern wie 01: 24: 51,123, aber du schneidest endlich 3, was zu tun ist?
Naanu

@naanu nur verwendenmillisLeft%1000
Lê Quang Duy

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
}

Die Antwort hängt von der Zeitzone ab, was bedeutet, dass das Ergebnis unterschiedlich ist, wenn es in verschiedenen Zeitzonen ausgeführt wird.
Derek Mahar

6

Das hat bei mir mit Kotlin funktioniert

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"
            }
        }
    }

Hat perfekt für mich funktioniert. Dies sollte die beste Antwort sein, da es null Stunden behandelt
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);

Dies druckt:

01:00:00

Sie machen es richtig, dass Bibliotheksmethoden die Konvertierungen für Sie durchführen. java.time, die moderne Java-API für Datum und Uhrzeit, oder genauer gesagt, ihre DurationKlasse macht es eleganter und weniger fehleranfällig als TimeUnit.

Die toMinutesPartund toSecondsPartMethoden, die ich verwendet habe, wurden in Java 9 eingeführt.

Java 6, 7 und 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);

Die Ausgabe ist die gleiche wie oben.

Frage: Wie kann das in Java 6 und 7 funktionieren?

  • In Java 8 und höher und auf neueren Android-Geräten (ab API-Level 26, wurde mir gesagt) java.time integriert.
  • In Java 6 und 7 erhalten Sie den ThreeTen Backport, den Backport der modernen Klassen (ThreeTen für JSR 310; siehe die Links unten).
  • Verwenden Sie auf (älteren) Android die Android-Edition von ThreeTen Backport. Es heißt ThreeTenABP. Und stellen Sie sicher, dass Sie die Datums- und org.threeten.bpZeitklassen mit Unterpaketen importieren.

Links


5

Der folgende Code führt die Konvertierung in beide Richtungen durch

23: 59: 58: 999 bis 86398999

und dann

86398999 bis 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;
    }
}

Ich habe diese Lösung positiv bewertet. Setzen Sie einfach einen Punkt zwischen sec und mls. Und ich weiß nicht, warum die Handhabung von Zeiten und Datumsangaben in Java sooooo schwierig ist. Die am häufigsten verwendeten Funktionen sollten bereits verfügbar und Teil der Klasse sein.
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)));

Format: 00: 00: 00.000

Beispiel: 615605 Millisecend

00: 10: 15.605


5

Die als richtig gekennzeichnete Antwort hat einen kleinen Fehler.

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

Zum Beispiel ist dies ein Beispiel für den Wert, den ich bekomme:

417474:44:19

Dies ist die Lösung, um das richtige Format zu erhalten:

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

als Ergebnis ein korrektes Format erhalten:

18:44:19

Eine andere Option, um das Format zu erhalten, hh:mm:ssist nur:

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

4

Ich habe es wie in der ersten Antwort gezeigt versucht. Es funktioniert, aber Minus brachte mich in Verwirrung. Meine Antwort von 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

Für Kotlin

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

wo milSecsist Millisekunden


1

Nun, Sie könnten so etwas versuchen:

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

Millisekunden in einen Zeitwert umwandeln

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.