Come convertire i millisecondi in "X minuti, x secondi" in Java?


573

Voglio registrare il tempo utilizzato System.currentTimeMillis()quando un utente inizia qualcosa nel mio programma. Al termine, sottrarrò la corrente System.currentTimeMillis()dalla startvariabile e voglio mostrare loro il tempo trascorso usando un formato leggibile come "XX ore, XX minuti, XX secondi" o anche "XX minuti, XX secondi" perché è è improbabile che impieghi qualcuno un'ora.

Qual'è il miglior modo per farlo?


5
Se impiegano più di un'ora, puoi comunque stampare qualcosa del genere; 90 minuti, 53 secondi.
Peter Lawrey,

1
la mia risposta arriva con 6 anni di ritardo, ma penso che sia più generico di quelli accettati: stackoverflow.com/a/35082080/82609
Sebastien Lorber,

Risposte:


1229

Usa la java.util.concurrent.TimeUnitclasse:

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

Nota: TimeUnitfa parte delle specifiche Java 1.5, ma è toMinutesstato aggiunto a partire da Java 1.6.

Per aggiungere uno zero iniziale per i valori 0-9, basta fare:

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

Se TimeUnito toMinutesnon sono supportati (come su Android prima dell'API versione 9), utilizzare le seguenti equazioni:

int seconds = (int) (milliseconds / 1000) % 60 ;
int minutes = (int) ((milliseconds / (1000*60)) % 60);
int hours   = (int) ((milliseconds / (1000*60*60)) % 24);
//etc...

5
int months = (int) ((float) giorni / 30.4368499f); int anni = (int) ((float) giorni / 365.242199f);
Nathan Schwermann

7
Id suggerisco di usare la mod 60 invece di sottrarre i minuti, sembra più pulito. Tuttavia, bisogna sapere che 1 minuto = 60 secondi per farlo ... =)
Per Alexandersson,

2
@AndreasDietrich SimpleDateFormat non funziona per differenze di tempo in quanto è solo data di ritorno dall'epoca!
Muhammad Babar,

5
int hours = (int) ((milliseconds / (1000*60*60)) % 24)questo non funziona! invece dovrebbe essere cosìint hours = (int) (milliseconds / (1000*60*60)) ;
Muhammad Babar,

5
Se qualcuno vuole un formato per i file video ( h: mm: ss ):String.format("%01d:%02d:%02d", hours, minutes, seconds);
kazy il

124

Sulla base della risposta di @ siddhadev, ho scritto una funzione che converte i millisecondi in una stringa formattata:

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

2
Dovresti fare un controllo lì per singolo / multiplo, al fine di evitare questo tipo di situazione:1 Days 1 Hours 1 Minutes 1 Seconds
Daniel

7
Potremmo usare la funzione modulo invece della sottrazione: 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; e anche il metodo String.format: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));

stampe:

25: 36: 259


1
Mi piace l'approccio di cui sopra il migliore se non altro per la sua semplicità! Dato che abbiamo a che fare con tempi e durate di solito uso Joda. Un esempio se hai due DateTime, inizia e termina rispettivamente:Duration dur = new Duration(start, end); long millis = dur.getMillis();
TechTrip

1
Avrei dovuto notare 2 modi per usare i formattatori Joda. Prima variazione sul tema: DateTimeFormat.forPattern("mm:ss:SSS").print(new DateTime(time)); oppure converti la Durata in un Periodo che può essere stampato automaticamente usando una Joda PeriodFormatter. La conversione potrebbe avere una perdita di precisione se diversa dalla cronologia ISO. Supponi una durata rappresentata dalla variabile duration. Period period = duration.toPeriod().normalizedStandard(PeriodType.time()); PeriodFormat.getDefault().print(period)) L'output è fantastico: 1 secondo e 581 millisecondi, rispondendo alla domanda principale sopra.
TechTrip

2
Un po 'tardi qui :) Ma non avresti bisogno di inserire simpleDateFormat.setTimezone (TimeZone.getTimeZone ("GMT")) a meno che non sia il tuo fuso orario reale?
Olle Söderström,

@ OlleSöderström C'è davvero un problema con il fuso orario qui. Ma impostandolo su GMT o UTC, la parte dell'ora sarà 12 anziché 0 per tutte le durate inferiori a 1 ora.
Episodex,

2
Il fuso orario non è l'unico problema qui ... questa risposta è fuorviante e potrebbe confondere seriamente i neofiti di Java. Anche ignorando le parentesi esterne ridondanti, l'OP ha chiesto come presentare una durata (una differenza tra due punti nel tempo, misurata in ms). Chiamare quella durata "tempo" e trattarla come un offset dal 1 ° gennaio 1970 solo per il gusto di formattare i suoi componenti più piccoli è ... imo sbagliato. Inoltre, lo stesso approccio era già stato suggerito 3 anni prima da questa risposta (vedere i commenti lì per maggiori dettagli sui problemi del fuso orario).
Amos M. Carpenter,

36

Uhm ... quanti millisecondi ci sono in un secondo? E tra un minuto? La divisione non è così difficile.

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

Continua così per ore, giorni, settimane, mesi, anni, decenni, qualunque cosa.


2
In realtà, farlo per qualcosa di più di un'ora non è una buona idea poiché i risultati potrebbero essere errati / non intuitivi quando sono coinvolti l'ora legale (giorni di 23 o 24 ore) o gli anni bisestili. Se leggessi "X accadrà tra 1 anno / mese", mi aspetto che sia la stessa data e ora.
Michael Borgwardt,

5
System.currentTimeMillis () è immune contro l'ora legale, quindi questo non verrà confuso da ore aggiuntive o mancanti. Se devi mostrare la differenza tra due date specifiche, è meglio costruire oggetti Date con il tempo dato e mostrare la differenza tra quelle due.
Bombe

1
Oltre le settimane, non è definito, poiché la lunghezza del mese è variabile. Quindi, in effetti, è necessario calcolare relativamente a un determinato riferimento temporale.
PhiLho,

31

Utilizzando il pacchetto java.time in Java 8:

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

L'output è nel formato di durata ISO 8601 : PT1M3.553S(1 minuto e 3,553 secondi).



1
(ANDROID) Richiede il livello API 26
Someone Somewhere

1
@SomeoneSomewhere Per Android con livello API 26, utilizzare il backport, vedere Come utilizzare ThreeTenABP in Progetto Android .
Ole VV,

1
È fantastico :) grazie per l'heads-up!
Someone Somewhere,

27

Non vorrei aggiungere la dipendenza extra solo per questo (la divisione non è poi così difficile), ma se si utilizza comunque Commons Lang, ci sono DurationFormatUtils .

Esempio di utilizzo (adattato da qui ):

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

Esempio:

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

//Output: 2s

Nota : per ottenere millis da due oggetti LocalDateTime è possibile utilizzare:

long age = ChronoUnit.MILLIS.between(initTime, LocalDateTime.now())

1
Fantastico, mi stavo solo chiedendo se esistesse una solida biblioteca che includesse questo genere di cose.
Lajcik,

Poiché un collegamento non è generalmente molto utile, ho aggiunto un esempio su come può essere utilizzato.
lepe,

26

Divisioni manuali o utilizzare l' API SimpleDateFormat .

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

Modifica di Bombe : nei commenti è stato dimostrato che questo approccio funziona solo per periodi più piccoli (ovvero meno di un giorno).


Wow. Questo è un trucco malvagio, che dipende dal fuso orario. Si interromperà senza pietà quando si ha un offset del fuso orario che non è un multiplo di 60 minuti (e abbiamo un paio di quei fastidiosi fusi orari di offset di 30 minuti nel mondo).
Bombe

Inoltre, si interromperà non appena si includono le ore nella stringa di formato e non sono GMT + 0, per gli stessi motivi.
Bombe

Noi facciamo? Veramente? Dove? Non dubitare di te, non ne ho mai sentito parlare prima - qualche nuova trappola da considerare ;-)
Treb

Sì. Controlla "Elenco dei fusi orari" su Wikipedia, ad esempio il Nepal è GMT + 05: 45.
Bombe

2
cadrian, ora funzionerà solo per durate meno di un giorno. Il numero di ore sarà sempre compreso tra 0 e 23, inclusi.
Bombe

21

Solo per aggiungere ulteriori informazioni se si desidera formattare come: HH: mm: ss

0 <= HH <= infinito

0 <= mm <60

0 <= ss <60

Usa questo:

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

Ho appena avuto questo problema ora e ho capito


1
La migliore risposta qui. Perché tutti vogliono rendere le cose così complicate? Questa è semplice matematica, gente.
Lambart,

11

Penso che il modo migliore sia:

String.format("%d min, %d sec", 
    TimeUnit.MILLISECONDS.toSeconds(length)/60,
    TimeUnit.MILLISECONDS.toSeconds(length) % 60 );

per minuti puoi usare TimeUnit.MILLISECONDS.toMinutes (lunghezza)
EminenT

11

Soluzione più breve:

Ecco probabilmente il più breve che si occupa anche dei fusi orari.

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

Quali output ad esempio:

00:18:32

Spiegazione:

%tTè l'ora formattata per l'orologio a 24 ore come %tH:%tM:%tS.

%tTaccetta anche i long come input, quindi non è necessario creare un Date. printf()stamperà semplicemente l'ora specificata in millisecondi, ma nel fuso orario corrente pertanto dobbiamo sottrarre l'offset grezzo del fuso orario corrente in modo che 0 millisecondi sarà 0 ore e non il valore di offset dell'orario corrente.

Nota n. 1: se hai bisogno del risultato come a String, puoi ottenerlo in questo modo:

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

Nota n. 2: questo dà solo il risultato corretto se millisè inferiore a un giorno perché la parte del giorno non è inclusa nell'output.


Questa è una scorciatoia così grande, ma quando la uso non ottengo i risultati previsti. Quindi ho: long millis = 8398;e quando lo passo alla String.format("%tT", millis)mia uscita sono le 19:00:08. Da dove viene il 19?
Nelda.techspiress,

1
@ Nelda.techspiress Questo è l'offset del tuo fuso orario. Devi sottrarre TimeZone.getDefault().getRawOffset()da esso, esattamente come scritto nella risposta:String.format("%tT", millis-TimeZone.getDefault().getRawOffset())
icza

che se ne è preso cura. Grazie per il chiarimento.
Nelda.techspiress,

8

Joda-Time

Utilizzando Joda-Time :

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

1
Non ce n'è bisogno PeriodFormatnell'ultima riga. Chiama semplicemente Period::toStringper ottenere una stringa di durata ISO 8601 per impostazione predefinita.
Basil Bourque,

8

Rivisitando il contributo di @ brent-nash, potremmo usare la funzione modulo invece delle sottrazioni e usare il metodo String.format per la stringa del risultato:

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

6

per Android sotto 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)) 

5

Per i tempi piccoli, meno di un'ora, preferisco:

long millis = ...

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

per intervalli più lunghi:

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

Questo è un suggerimento prezioso, ci sono molte possibilità per data e ora con l'API Java Formatter ( docs.oracle.com/javase/8/docs/api/java/util/Formatter.html )! Potresti anche avere il risultato della condizione else con: System.out.printf ("% 1 $ tH:% 1 $ tM:% 1 $ tS% n", millis); o anche System.out.printf ("% 1 $ tT% n", millis);
Jose Tepedino,

@JoseTepedino ma sai che mostra %tH solo da 0 a 23 ore? Ciò significa che ad esempio verranno visualizzate 24 ore come 00, 25 ore in quanto 01... stesso valido per %tT- giorni verrà eliminato in silenzio. Certo, potrebbero anche essere visualizzati giorni, ma sarebbe un eccesso per il problema che ho avuto quando ho scritto questo (nel 2011) [:-)
user85421

Vedo ... che funzionerebbe davvero solo per tempi inferiori a un giorno (24 ore). Grazie.
Jose Tepedino,

5

Il mio semplice calcolo:

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

Buona programmazione :)


Suppongo che long sia più appropriato per questa funzione poiché System.currentTimeMillis () restituisce un valore lungo.
aprodan,

Questo non è corretto, hai controllato l'output?
Jorgesys,

4

Ecco una risposta basata sulla risposta di Brent Nash, spero che ti aiuti!

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

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

3
La formula alla riga 6 è errata. diff=diff-(hours*60*1000);dovrebbe essere diff=diff-(hours*60*60*1000);. Ho provato a modificarlo, ma la fastidiosa politica di modifica di StackOverflow dice che non sono sufficienti caratteri per una modifica.
quux00,

4

In primo luogo, System.currentTimeMillis()e Instant.now()non sono l'ideale per il tempismo. Entrambi riportano l'ora dell'orologio da parete, che il computer non conosce con precisione, e che può spostarsi in modo irregolare, incluso tornare indietro se, ad esempio, il demone NTP corregge l'ora di sistema. Se il tuo tempismo si verifica su un singolo computer, dovresti invece utilizzare System.nanoTime () .

In secondo luogo, da Java 8 in poi java.time.Duration è il modo migliore per rappresentare una durata:

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"

3

Se sai che la differenza oraria sarebbe inferiore a un'ora, puoi utilizzare il seguente codice:

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

Il risultato sarà: 51:00


3

Questa risposta è simile ad alcune risposte sopra. Tuttavia, ritengo che sarebbe utile perché, a differenza di altre risposte, questo rimuoverà eventuali virgole o spazi bianchi in più e gestirà l'abbreviazione.

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

3

C'è un problema. Quando i millisecondi sono 59999, in realtà sono 1 minuto ma verranno calcolati come 59 secondi e 999 millisecondi vengono persi.

Ecco una versione modificata basata su risposte precedenti, che può risolvere questa perdita:

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

2

Questo è più facile in Java 9:

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

Questo produce una stringa come 0 hours, 39 mins, 9 seconds.

Se vuoi arrotondare a interi secondi prima della formattazione:

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

Per lasciare fuori gli orari se sono 0:

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

Ora possiamo avere per esempio 39 mins, 9 seconds.

Per stampare minuti e secondi con zero iniziale per renderli sempre a due cifre, basta inserire 02nei relativi identificatori di formato, quindi:

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

Ora possiamo avere per esempio 0 hours, 39 mins, 09 seconds.


Qualche formattazione per rimuovere ore / minuti / secondi quando un numero precedente è 0? Voglio dire, è realizzabile con la condizione if else, ma che dire dell'esistenza di tale formattazione di String o di qualcosa di simile?
Farid,

1
No, scusa, @FARID, è necessario if- elselì.
Ole VV,

1

per le stringhe corrette ("1 ora, 3 secondi", "3 minuti" ma non "0 ora, 0 minuti, 3 secondi") scrivo questo codice:

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

1

Ho modificato la risposta di @MyKuLLSKI e aggiunto il supporto per la plurlizzazione. Ho preso secondi perché non ne avevo bisogno, anche se sentiti libero di aggiungerlo nuovamente se ne hai bisogno.

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

int intervalMins vs long millis
Kiquenet,

1

Ho coperto questo in un'altra risposta ma puoi fare:

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

L'output è simile Map:{DAYS=1, HOURS=3, MINUTES=46, SECONDS=40, MILLISECONDS=0, MICROSECONDS=0, NANOSECONDS=0}, con le unità ordinate.

Sta a te capire come internazionalizzare questi dati in base alle impostazioni internazionali di destinazione.


1

Utilizzare java.util.concurrent.TimeUnit e utilizzare questo semplice metodo:

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

Per esempio:

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

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.