Wie konvertiere ich Millisekunden in Java in "X Minuten, x Sekunden"?

572

Ich möchte die Zeit aufzeichnen, mit der System.currentTimeMillis()ein Benutzer etwas in meinem Programm beginnt. Wenn er fertig ist, subtrahiere ich den Strom System.currentTimeMillis()von der startVariablen und möchte ihnen die verstrichene Zeit in einem für Menschen lesbaren Format wie "XX Stunden, XX Minuten, XX Sekunden" oder sogar "XX Minuten, XX Sekunden" anzeigen, weil dies der Fall ist Es ist unwahrscheinlich, dass jemand eine Stunde braucht.

Was ist der beste Weg, dies zu tun?

Klicken Sie auf Upvote
quelle
5
Wenn sie länger als eine Stunde dauern, können Sie immer noch so etwas drucken. 90 Minuten, 53 Sekunden
Peter Lawrey
1
Meine Antwort kommt 6 Jahre zu spät, aber ich denke, es ist allgemeiner als akzeptiert: stackoverflow.com/a/35082080/82609
Sebastien Lorber
1
Schauen Sie

Antworten:

1228

Verwenden Sie die java.util.concurrent.TimeUnitKlasse:

String.format("%d min, %d sec", 
    TimeUnit.MILLISECONDS.toMinutes(millis),
    TimeUnit.MILLISECONDS.toSeconds(millis) - 
    TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(millis))
);

Hinweis: TimeUnitist Teil der Java 1.5-Spezifikation, wurde jedoch toMinutesab Java 1.6 hinzugefügt.

Um eine führende Null für die Werte 0-9 hinzuzufügen, gehen Sie einfach wie folgt vor:

String.format("%02d min, %02d sec", 
    TimeUnit.MILLISECONDS.toMinutes(millis),
    TimeUnit.MILLISECONDS.toSeconds(millis) - 
    TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(millis))
);

Wenn TimeUnitoder toMinutesnicht unterstützt werden (z. B. unter Android vor API Version 9), verwenden Sie die folgenden Gleichungen:

int seconds = (int) (milliseconds / 1000) % 60 ;
int minutes = (int) ((milliseconds / (1000*60)) % 60);
int hours   = (int) ((milliseconds / (1000*60*60)) % 24);
//etc...
Siddhadev
quelle
5
int Monate = (int) ((float) Tage / 30.4368499f); int Jahre = (int) ((float) Tage / 365.242199f);
Nathan Schwermann
7
Ich würde vorschlagen, Mod 60 zu verwenden, anstatt die Minuten zu subtrahieren, es sieht sauberer aus. Allerdings muss man wissen, dass 1 min = 60 sec, um das zu tun ... =)
Per Alexandersson
2
@AndreasDietrich SimpleDateFormat funktioniert nicht für Zeitunterschiede, da es nur das Datum aus der Epoche zurückgibt!
Muhammad Babar
5
int hours = (int) ((milliseconds / (1000*60*60)) % 24)das funktioniert nicht! stattdessen sollte es so seinint hours = (int) (milliseconds / (1000*60*60)) ;
Muhammad Babar
5
Wenn jemand ein Format für Videodateien möchte ( h: mm: ss ):String.format("%01d:%02d:%02d", hours, minutes, seconds);
Kazy
124

Basierend auf der Antwort von @ siddhadev habe ich eine Funktion geschrieben, die Millisekunden in eine formatierte Zeichenfolge konvertiert:

   /**
     * Convert a millisecond duration to a string format
     * 
     * @param millis A duration to convert to a string form
     * @return A string of the form "X Days Y Hours Z Minutes A Seconds".
     */
    public static String getDurationBreakdown(long millis) {
        if(millis < 0) {
            throw new IllegalArgumentException("Duration must be greater than zero!");
        }

        long days = TimeUnit.MILLISECONDS.toDays(millis);
        millis -= TimeUnit.DAYS.toMillis(days);
        long hours = TimeUnit.MILLISECONDS.toHours(millis);
        millis -= TimeUnit.HOURS.toMillis(hours);
        long minutes = TimeUnit.MILLISECONDS.toMinutes(millis);
        millis -= TimeUnit.MINUTES.toMillis(minutes);
        long seconds = TimeUnit.MILLISECONDS.toSeconds(millis);

        StringBuilder sb = new StringBuilder(64);
        sb.append(days);
        sb.append(" Days ");
        sb.append(hours);
        sb.append(" Hours ");
        sb.append(minutes);
        sb.append(" Minutes ");
        sb.append(seconds);
        sb.append(" Seconds");

        return(sb.toString());
    }
Brent schreibt Code
quelle
2
Sie sollten dort eine Überprüfung auf einzeln / mehrfach durchführen, um diese Art von Situation zu vermeiden:1 Days 1 Hours 1 Minutes 1 Seconds
Daniel
7
Wir könnten die long days = TimeUnit.MILLISECONDS.toDays(millis); long hours = TimeUnit.MILLISECONDS.toHours(millis) % 24; long minutes = TimeUnit.MILLISECONDS.toMinutes(millis) % 60; long seconds = TimeUnit.MILLISECONDS.toSeconds(millis) % 60; long milliseconds = millis % 1000; Modulfunktion anstelle der Subtraktion verwenden: und auch die String.format-Methode:return String.format("%d Days %d Hours %d Minutes %d Seconds %d Milliseconds", days, hours, minutes, seconds, milliseconds);
Jose Tepedino
78
long time = 1536259;

return (new SimpleDateFormat("mm:ss:SSS")).format(new Date(time));

Drucke:

25: 36: 259

Damien
quelle
1
Ich mag den obigen Ansatz am besten, wenn nicht umsonst seine Einfachheit! Da es sich um Zeiten und Dauern handelt, verwende ich normalerweise Joda. Ein Beispiel, wenn Sie zwei DateTimes haben, beginnen und enden jeweils:Duration dur = new Duration(start, end); long millis = dur.getMillis();
TechTrip
1
Ich hätte zwei Möglichkeiten zur Verwendung von Joda-Formatierern beachten sollen. Erste Variation Ihres Themas: DateTimeFormat.forPattern("mm:ss:SSS").print(new DateTime(time)); Oder konvertieren Sie die Dauer in einen Zeitraum, der automatisch mit einem Joda gedruckt werden kann PeriodFormatter. Die Konvertierung kann zu Genauigkeitsverlusten führen, wenn keine andere ISO-Chronologie vorliegt. Angenommen, eine Dauer, die durch die Variable dargestellt wird duration. Period period = duration.toPeriod().normalizedStandard(PeriodType.time()); PeriodFormat.getDefault().print(period)) Die Ausgabe ist fantastisch: 1 Sekunde und 581 Millisekunden, Beantwortung der obigen Hauptfrage.
TechTrip
2
Ein bisschen spät hier :) Aber müssten Sie nicht simpleDateFormat.setTimezone (TimeZone.getTimeZone ("GMT")) hier einfügen, es sei denn, dies ist Ihre tatsächliche Zeitzone?
Olle Söderström
@ OlleSöderström Hier gibt es tatsächlich ein Problem mit der Zeitzone. Wenn Sie jedoch GMT oder UTC einstellen, ist der Stundenanteil für alle Zeiträume von weniger als 1 Stunde 12 statt 0.
Episodex
2
Zeitzone ist hier nicht das einzige Problem ... Diese Antwort ist irreführend und könnte Java-Neulinge ernsthaft verwirren. Selbst wenn die redundanten äußeren Klammern ignoriert wurden, fragte das OP, wie eine Dauer dargestellt werden soll (eine Differenz zwischen zwei Zeitpunkten, gemessen in ms). Diese Dauer "Zeit" zu nennen und sie seit dem 1. Januar 1970 als Offset zu behandeln, nur um die kleineren Komponenten zu formatieren, ist einfach ... falsch imo. Darüber hinaus wurde mit dieser Antwort bereits 3 Jahre zuvor derselbe Ansatz vorgeschlagen (siehe Kommentare dort für weitere Einzelheiten zu Zeitzonenproblemen).
Amos M. Carpenter
36

Ähm ... wie viele Millisekunden sind in einer Sekunde? Und in einer Minute? Teilung ist nicht so schwer.

int seconds = (int) ((milliseconds / 1000) % 60);
int minutes = (int) ((milliseconds / 1000) / 60);

Fahren Sie so für Stunden, Tage, Wochen, Monate, Jahre, Jahrzehnte fort, was auch immer.

Bombe
quelle
2
Tatsächlich ist es keine gute Idee, dies länger als eine Stunde zu tun, da die Ergebnisse falsch / nicht intuitiv sein können, wenn Sommerzeit (Tage von 23 oder 24 Stunden) oder Schaltjahre betroffen sind. Wenn ich lese "X wird in 1 Jahr / Monat passieren", würde ich erwarten, dass es das gleiche Datum und die gleiche Uhrzeit ist.
Michael Borgwardt
5
System.currentTimeMillis () ist immun gegen Sommerzeit, sodass dies nicht durch zusätzliche oder fehlende Stunden verwechselt wird. Wenn Sie den Unterschied zwischen zwei bestimmten Daten anzeigen müssen, ist es besser, Datumsobjekte mit der angegebenen Zeit zu erstellen und den Unterschied zwischen diesen beiden anzuzeigen.
Bombe
1
Über Wochen hinaus ist es undefiniert, da die Monatslänge variabel ist. In der Tat müssen Sie also relativ zu einer bestimmten Zeitreferenz berechnen.
PhiLho
31

Verwenden des Pakets java.time in Java 8:

Instant start = Instant.now();
Thread.sleep(63553);
Instant end = Instant.now();
System.out.println(Duration.between(start, end));

Die Ausgabe erfolgt nach ISO 8601. Dauer Format : PT1M3.553S(1 Minute und 3,553 Sekunden).

Vitalii Fedorenko
quelle
1
(ANDROID) Benötigt API Level 26
Jemand irgendwo
1
@SomeoneSomewhere Verwenden Sie für Android unter API-Ebene 26 den Backport, siehe Verwendung von ThreeTenABP in Android Project .
Ole VV
1
Das ist großartig :) Danke für das Heads-up!
Jemand irgendwo
27

Ich würde die zusätzliche Abhängigkeit nicht nur dafür heranziehen (die Aufteilung ist schließlich nicht so schwer), aber wenn Sie Commons Lang trotzdem verwenden, gibt es die DurationFormatUtils .

Anwendungsbeispiel (angepasst von hier ):

import org.apache.commons.lang3.time.DurationFormatUtils

public String getAge(long value) {
    long currentTime = System.currentTimeMillis();
    long age = currentTime - value;
    String ageString = DurationFormatUtils.formatDuration(age, "d") + "d";
    if ("0d".equals(ageString)) {
        ageString = DurationFormatUtils.formatDuration(age, "H") + "h";
        if ("0h".equals(ageString)) {
            ageString = DurationFormatUtils.formatDuration(age, "m") + "m";
            if ("0m".equals(ageString)) {
                ageString = DurationFormatUtils.formatDuration(age, "s") + "s";
                if ("0s".equals(ageString)) {
                    ageString = age + "ms";
                }
            }
        }
    }
    return ageString;
}   

Beispiel:

long lastTime = System.currentTimeMillis() - 2000;
System.out.println("Elapsed time: " + getAge(lastTime)); 

//Output: 2s

Hinweis : Um Millis von zwei LocalDateTime-Objekten abzurufen, können Sie Folgendes verwenden:

long age = ChronoUnit.MILLIS.between(initTime, LocalDateTime.now())
Thilo
quelle
1
Großartig, ich habe mich nur gefragt, ob es eine robuste Bibliothek gibt, die solche Dinge enthält.
Lajcik
Da ein Link im Allgemeinen nicht sehr nützlich ist, habe ich ein Beispiel hinzugefügt, wie er verwendet werden kann.
Lepe
26

Entweder Handunterteilungen oder die SimpleDateFormat-API verwenden .

long start = System.currentTimeMillis();
// do your work...
long elapsed = System.currentTimeMillis() - start;
DateFormat df = new SimpleDateFormat("HH 'hours', mm 'mins,' ss 'seconds'");
df.setTimeZone(TimeZone.getTimeZone("GMT+0"));
System.out.println(df.format(new Date(elapsed)));

Bearbeiten von Bombe : In den Kommentaren wurde gezeigt, dass dieser Ansatz nur für kleinere Zeiträume (dh weniger als einen Tag) funktioniert.

Cadrian
quelle
Beeindruckend. Das ist ein böser, zeitzonenabhängiger Hack. Es wird gnadenlos brechen, wenn Sie einen Zeitzonenversatz haben, der nicht ein Vielfaches von 60 Minuten beträgt (und wir haben einige dieser lästigen 30-Minuten-Versatz-Zeitzonen auf der Welt).
Bombe
Außerdem wird es genauso schlecht brechen, sobald Sie die Stunden in die Formatzeichenfolge aufnehmen und aus den gleichen Gründen nicht bei GMT + 0 sind.
Bombe
Wir tun? "Ja wirklich?" Wo? Ohne an dir zu zweifeln, habe noch nie davon gehört - eine neue Falle, die es zu beachten gilt ;-)
Treb
Ja. Überprüfen Sie "Liste der Zeitzonen" auf Wikipedia, z. B. Nepal ist bei GMT + 05: 45.
Bombe
2
Cadrian, jetzt funktioniert es nur noch für eine Dauer von weniger als einem Tag. Die Anzahl der Stunden liegt immer zwischen 0 und 23 einschließlich.
Bombe
21

Nur um weitere Informationen hinzuzufügen, wenn Sie wie folgt formatieren möchten: HH: mm: ss

0 <= HH <= unendlich

0 <= mm <60

0 <= ss <60

benutze das:

int h = (int) ((startTimeInMillis / 1000) / 3600);
int m = (int) (((startTimeInMillis / 1000) / 60) % 60);
int s = (int) ((startTimeInMillis / 1000) % 60);

Ich hatte gerade dieses Problem und habe es herausgefunden

Fredcrs
quelle
1
Beste Antwort hier. Warum will jeder die Dinge so kompliziert machen? Das ist einfache Mathematik, Leute.
Lambart
11

Ich denke, der beste Weg ist:

String.format("%d min, %d sec", 
    TimeUnit.MILLISECONDS.toSeconds(length)/60,
    TimeUnit.MILLISECONDS.toSeconds(length) % 60 );
Xtera
quelle
Für Minuten können Sie TimeUnit.MILLISECONDS.toMinutes (Länge)
EminenT
11

Kürzeste Lösung:

Hier ist wahrscheinlich die kürzeste, die sich auch mit Zeitzonen befasst.

System.out.printf("%tT", millis-TimeZone.getDefault().getRawOffset());

Welche Ausgänge zum Beispiel:

00:18:32

Erläuterung:

%tTist die für die 24-Stunden-Uhr formatierte Zeit als %tH:%tM:%tS.

%tTAkzeptiert auch Longs als Eingabe, sodass keine erstellt werden muss Date.printf()druckt einfach die in Millisekunden angegebene Zeit, aber in der aktuellen Zeitzone müssen wir daher den Rohversatz der aktuellen Zeitzone subtrahieren, sodass 0 Millisekunden 0 Stunden und nicht der Zeitversatzwert der aktuellen Zeitzone sind.

Hinweis Nr. 1: Wenn Sie das Ergebnis als benötigen String, können Sie es folgendermaßen erhalten:

String t = String.format("%tT", millis-TimeZone.getDefault().getRawOffset());

Hinweis 2: Dies liefert nur dann ein korrektes Ergebnis, wenn millises weniger als einen Tag beträgt, da der Tagesteil nicht in der Ausgabe enthalten ist.

icza
quelle
Dies ist eine großartige Abkürzung, aber wenn ich sie verwende, erhalte ich nicht die erwarteten Ergebnisse. Also habe ich: long millis = 8398;und wenn ich das an String.format("%tT", millis)meine Ausgabe weitergebe, ist es 19:00:08. Woher kommen die 19?
Nelda.techspiress
1
@ Nelda.techspiress Das ist der Versatz Ihrer Zeitzone. Sie müssen davon subtrahieren TimeZone.getDefault().getRawOffset(), genau wie in der Antwort geschrieben:String.format("%tT", millis-TimeZone.getDefault().getRawOffset())
icza
das hat sich darum gekümmert. Danke für das Aufklären.
Nelda.techspiress
8

Joda-Zeit

Verwenden der Joda-Zeit :

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));
Dogbane
quelle
1
Das ist PeriodFormatin der letzten Zeile nicht nötig . Rufen Sie einfach Period::toStringan, um standardmäßig eine ISO 8601 Duration- Zeichenfolge zu erhalten.
Basil Bourque
8

Bei einem erneuten Besuch des @ brent-nash-Beitrags könnten wir die Modulfunktion anstelle von Subtraktionen verwenden und die String.format-Methode für die Ergebniszeichenfolge verwenden:

  /**
   * Convert a millisecond duration to a string format
   * 
   * @param millis A duration to convert to a string form
   * @return A string of the form "X Days Y Hours Z Minutes A Seconds B Milliseconds".
   */
   public static String getDurationBreakdown(long millis) {
       if (millis < 0) {
          throw new IllegalArgumentException("Duration must be greater than zero!");
       }

       long days = TimeUnit.MILLISECONDS.toDays(millis);
       long hours = TimeUnit.MILLISECONDS.toHours(millis) % 24;
       long minutes = TimeUnit.MILLISECONDS.toMinutes(millis) % 60;
       long seconds = TimeUnit.MILLISECONDS.toSeconds(millis) % 60;
       long milliseconds = millis % 1000;

       return String.format("%d Days %d Hours %d Minutes %d Seconds %d Milliseconds",
                            days, hours, minutes, seconds, milliseconds);
   }
Jose Tepedino
quelle
6

für Android unter API 9

(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)) 
Pradeep
quelle
5

Für kleine Zeiten, weniger als eine Stunde, bevorzuge ich:

long millis = ...

System.out.printf("%1$TM:%1$TS", millis);
// or
String str = String.format("%1$TM:%1$TS", millis);

für längere Intervalle:

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);
}
user85421
quelle
Das ist ein wertvoller Hinweis, es gibt viele solcher Möglichkeiten für Datum und Uhrzeit mit der Java Formatter API ( docs.oracle.com/javase/8/docs/api/java/util/Formatter.html )! Sie könnten auch das Ergebnis der else-Bedingung haben mit: System.out.printf ("% 1 $ tH:% 1 $ tM:% 1 $ tS% n", millis); oder sogar System.out.printf ("% 1 $ tT% n", Millis);
Jose Tepedino
@ JoseTepedino, aber Sie wissen, dass %tH nur von 0 bis 23 Stunden zeigt? Das bedeutet, dass zum Beispiel 24 Stunden als angezeigt werden 00, 25 Stunden als 01... dasselbe Gültig für %tT- Tage wird stillschweigend verworfen. Sicher, es könnten auch Tage angezeigt werden, aber das wäre ein Overkill für das Problem, das ich hatte, als ich dies schrieb (im Jahr 2011) [:-)
user85421
Ich verstehe ... das würde wirklich nur für Zeiten von weniger als einem Tag (24 Stunden) funktionieren. Vielen Dank.
Jose Tepedino
5

Meine einfache Berechnung:

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

Viel Spaß beim Codieren :)

Shohan Ahmed Sijan
quelle
Ich nehme an, long ist für diese Funktion besser geeignet, da System.currentTimeMillis () einen langen Wert zurückgibt.
Aprodan
Dies ist nicht korrekt. Haben Sie die Ausgabe überprüft?
Jorgesys
4

Hier ist eine Antwort basierend auf Brent Nash Antwort, Hoffnung, die hilft!

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());
}
Reda Bouaichi
quelle
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
Fathah Rehman P.
quelle
3
Die Formel in Zeile 6 ist falsch. diff=diff-(hours*60*1000);sollte sein diff=diff-(hours*60*60*1000);. Ich habe versucht, es zu bearbeiten, aber die nervige Bearbeitungsrichtlinie von StackOverflow besagt, dass nicht genügend Zeichen für eine Bearbeitung vorhanden sind.
quux00
4

Erstens System.currentTimeMillis()und Instant.now()sind nicht ideal für das Timing. Beide melden die Wanduhrzeit, die der Computer nicht genau kennt und die sich unregelmäßig bewegen kann, einschließlich des Rückwärtsgehens, wenn beispielsweise der NTP-Dämon die Systemzeit korrigiert. Wenn Ihr Timing auf einem einzelnen Computer stattfindet, sollten Sie stattdessen System.nanoTime () verwenden. .

Zweitens ist java.time.Duration ab Java 8 der beste Weg, um eine Dauer darzustellen:

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"
MikeFHay
quelle
3

Wenn Sie wissen, dass der Zeitunterschied weniger als eine Stunde beträgt, können Sie den folgenden Code verwenden:

    Calendar c1 = Calendar.getInstance();
    Calendar c2 = Calendar.getInstance();

    c2.add(Calendar.MINUTE, 51);

    long diff = c2.getTimeInMillis() - c1.getTimeInMillis();

    c2.set(Calendar.MINUTE, 0);
    c2.set(Calendar.HOUR, 0);
    c2.set(Calendar.SECOND, 0);

    DateFormat df = new SimpleDateFormat("mm:ss");
    long diff1 = c2.getTimeInMillis() + diff;
    System.out.println(df.format(new Date(diff1)));

Es ergibt sich: 51:00

Gourav Singla
quelle
3

Diese Antwort ähnelt einigen Antworten oben. Ich bin jedoch der Meinung, dass dies von Vorteil ist, da dadurch im Gegensatz zu anderen Antworten zusätzliche Kommas oder Leerzeichen entfernt werden und die Abkürzung behandelt wird.

/**
 * Converts milliseconds to "x days, x hours, x mins, x secs"
 * 
 * @param millis
 *            The milliseconds
 * @param longFormat
 *            {@code true} to use "seconds" and "minutes" instead of "secs" and "mins"
 * @return A string representing how long in days/hours/minutes/seconds millis is.
 */
public static String millisToString(long millis, boolean longFormat) {
    if (millis < 1000) {
        return String.format("0 %s", longFormat ? "seconds" : "secs");
    }
    String[] units = {
            "day", "hour", longFormat ? "minute" : "min", longFormat ? "second" : "sec"
    };
    long[] times = new long[4];
    times[0] = TimeUnit.DAYS.convert(millis, TimeUnit.MILLISECONDS);
    millis -= TimeUnit.MILLISECONDS.convert(times[0], TimeUnit.DAYS);
    times[1] = TimeUnit.HOURS.convert(millis, TimeUnit.MILLISECONDS);
    millis -= TimeUnit.MILLISECONDS.convert(times[1], TimeUnit.HOURS);
    times[2] = TimeUnit.MINUTES.convert(millis, TimeUnit.MILLISECONDS);
    millis -= TimeUnit.MILLISECONDS.convert(times[2], TimeUnit.MINUTES);
    times[3] = TimeUnit.SECONDS.convert(millis, TimeUnit.MILLISECONDS);
    StringBuilder s = new StringBuilder();
    for (int i = 0; i < 4; i++) {
        if (times[i] > 0) {
            s.append(String.format("%d %s%s, ", times[i], units[i], times[i] == 1 ? "" : "s"));
        }
    }
    return s.toString().substring(0, s.length() - 2);
}

/**
 * Converts milliseconds to "x days, x hours, x mins, x secs"
 * 
 * @param millis
 *            The milliseconds
 * @return A string representing how long in days/hours/mins/secs millis is.
 */
public static String millisToString(long millis) {
    return millisToString(millis, false);
}
Jared Rummler
quelle
3

Es gibt ein Problem. Wenn Millisekunden 59999 sind, ist es tatsächlich 1 Minute, aber es wird als 59 Sekunden berechnet und 999 Millisekunden gehen verloren.

Hier ist eine modifizierte Version, die auf früheren Antworten basiert und diesen Verlust beheben kann:

public static String formatTime(long millis) {
    long seconds = Math.round((double) millis / 1000);
    long hours = TimeUnit.SECONDS.toHours(seconds);
    if (hours > 0)
        seconds -= TimeUnit.HOURS.toSeconds(hours);
    long minutes = seconds > 0 ? TimeUnit.SECONDS.toMinutes(seconds) : 0;
    if (minutes > 0)
        seconds -= TimeUnit.MINUTES.toSeconds(minutes);
    return hours > 0 ? String.format("%02d:%02d:%02d", hours, minutes, seconds) : String.format("%02d:%02d", minutes, seconds);
}
Hexise
quelle
2

Dies ist in Java 9 einfacher:

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

Dies erzeugt eine Zeichenfolge wie 0 hours, 39 mins, 9 seconds.

Wenn Sie vor dem Formatieren auf ganze Sekunden runden möchten:

    elapsedTime = elapsedTime.plusMillis(500).truncatedTo(ChronoUnit.SECONDS);

So lassen Sie die Stunden weg, wenn sie 0 sind:

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

Jetzt können wir zum Beispiel haben 39 mins, 9 seconds.

Um Minuten und Sekunden mit führender Null zu drucken, um sie immer zweistellig zu machen, fügen Sie einfach 02in die entsprechenden Formatspezifizierer ein, also:

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

Jetzt können wir zum Beispiel haben 0 hours, 39 mins, 09 seconds.

Ole VV
quelle
Gibt es eine Formatierung zum Entfernen von Stunden / Minuten / Sekunden, wenn eine vorhergehende Zahl 0 ist? Ich meine, es ist erreichbar mit wenn sonst Bedingung, aber was ist mit der Existenz einer solchen String-Formatierung oder etwas Nahem, gibt es welche?
Farid
1
Nein, sorry, @FARID, du brauchst if- elseda.
Ole VV
1

Für korrekte Zeichenfolgen ("1 Stunde, 3 Sekunden", "3 Minuten", aber nicht "0 Stunden, 0 Minuten, 3 Sekunden") schreibe ich diesen Code:

int seconds = (int)(millis / 1000) % 60 ;
int minutes = (int)((millis / (1000*60)) % 60);
int hours = (int)((millis / (1000*60*60)) % 24);
int days = (int)((millis / (1000*60*60*24)) % 365);
int years = (int)(millis / 1000*60*60*24*365);

ArrayList<String> timeArray = new ArrayList<String>();

if(years > 0)   
    timeArray.add(String.valueOf(years)   + "y");

if(days > 0)    
    timeArray.add(String.valueOf(days) + "d");

if(hours>0)   
    timeArray.add(String.valueOf(hours) + "h");

if(minutes>0) 
    timeArray.add(String.valueOf(minutes) + "min");

if(seconds>0) 
    timeArray.add(String.valueOf(seconds) + "sec");

String time = "";
for (int i = 0; i < timeArray.size(); i++) 
{
    time = time + timeArray.get(i);
    if (i != timeArray.size() - 1)
        time = time + ", ";
}

if (time == "")
  time = "0 sec";
John
quelle
1

Ich habe die Antwort von @MyKuLLSKI geändert und die Plurlisierungsunterstützung hinzugefügt. Ich habe Sekunden herausgenommen, weil ich sie nicht brauchte. Sie können sie jedoch jederzeit wieder hinzufügen, wenn Sie sie benötigen.

public static String intervalToHumanReadableTime(int intervalMins) {

    if(intervalMins <= 0) {
        return "0";
    } else {

        long intervalMs = intervalMins * 60 * 1000;

        long days = TimeUnit.MILLISECONDS.toDays(intervalMs);
        intervalMs -= TimeUnit.DAYS.toMillis(days);
        long hours = TimeUnit.MILLISECONDS.toHours(intervalMs);
        intervalMs -= TimeUnit.HOURS.toMillis(hours);
        long minutes = TimeUnit.MILLISECONDS.toMinutes(intervalMs);

        StringBuilder sb = new StringBuilder(12);

        if (days >= 1) {
            sb.append(days).append(" day").append(pluralize(days)).append(", ");
        }

        if (hours >= 1) {
            sb.append(hours).append(" hour").append(pluralize(hours)).append(", ");
        }

        if (minutes >= 1) {
            sb.append(minutes).append(" minute").append(pluralize(minutes));
        } else {
            sb.delete(sb.length()-2, sb.length()-1);
        }

        return(sb.toString());          

    }

}

public static String pluralize(long val) {
    return (Math.round(val) > 1 ? "s" : "");
}
Bitstrom
quelle
int intervalMins vs long millis
Kiquenet
1

Ich habe dies in einer anderen Antwort behandelt, aber Sie können tun:

public static Map<TimeUnit,Long> computeDiff(Date date1, Date date2) {
    long diffInMillies = date2.getTime() - date1.getTime();
    List<TimeUnit> units = new ArrayList<TimeUnit>(EnumSet.allOf(TimeUnit.class));
    Collections.reverse(units);
    Map<TimeUnit,Long> result = new LinkedHashMap<TimeUnit,Long>();
    long milliesRest = diffInMillies;
    for ( TimeUnit unit : units ) {
        long diff = unit.convert(milliesRest,TimeUnit.MILLISECONDS);
        long diffInMilliesForUnit = unit.toMillis(diff);
        milliesRest = milliesRest - diffInMilliesForUnit;
        result.put(unit,diff);
    }
    return result;
}

Die Ausgabe ist so etwas wie Map:{DAYS=1, HOURS=3, MINUTES=46, SECONDS=40, MILLISECONDS=0, MICROSECONDS=0, NANOSECONDS=0}mit den bestellten Einheiten.

Es liegt an Ihnen, herauszufinden, wie Sie diese Daten entsprechend dem Zielgebietsschema internationalisieren können.

Sebastien Lorber
quelle
1

Verwenden Sie java.util.concurrent.TimeUnit und verwenden Sie diese einfache Methode:

private static long timeDiff(Date date, Date date2, TimeUnit unit) {
    long milliDiff=date2.getTime()-date.getTime();
    long unitDiff = unit.convert(milliDiff, TimeUnit.MILLISECONDS);
    return unitDiff; 
}

Zum Beispiel:

SimpleDateFormat sdf = new SimpleDateFormat("yy/MM/dd HH:mm:ss");  
Date firstDate = sdf.parse("06/24/2017 04:30:00");
Date secondDate = sdf.parse("07/24/2017 05:00:15");
Date thirdDate = sdf.parse("06/24/2017 06:00:15");

System.out.println("days difference: "+timeDiff(firstDate,secondDate,TimeUnit.DAYS));
System.out.println("hours difference: "+timeDiff(firstDate,thirdDate,TimeUnit.HOURS));
System.out.println("minutes difference: "+timeDiff(firstDate,thirdDate,TimeUnit.MINUTES));
System.out.println("seconds difference: "+timeDiff(firstDate,thirdDate,TimeUnit.SECONDS));
Aramis Rodríguez Blanco
quelle