Come convertire i millisecondi nel formato "hh: mm: ss"?


184

Non ho capito bene. Dopo essermi imbattuto in questo thread, ho cercato di capire come formattare un timer per il conto alla rovescia che avesse il formato hh:mm:ss.

Ecco il mio tentativo -

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

Quindi, quando provo un valore come 3600000ms, ottengo 01:59:00, il che è sbagliato dal momento che dovrebbe essere 01:00:00. Ovviamente c'è qualcosa che non va nella mia logica, ma al momento non riesco a vedere di cosa si tratti!

Qualcuno può aiutare?

Modificare -

Aggiustato. Ecco il modo giusto per formattare millisecondi per hh:mm:ssformattare:

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

Il problema era questo TimeUnit.MINUTES.toMinutes(TimeUnit.MILLISECONDS.toHours(millis)). TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(millis))Invece avrebbe dovuto essere questo .


1
3.600.000 millisecondi è 3.600 secondi, o 60 minuti o 1 ora. Non dovrebbe essere 00:59:59, dovrebbe essere 01:00:00.
Borealid,

Risposte:


355

Eri davvero vicino:

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

Stavi convertendo le ore in millisecondi usando i minuti anziché le ore .

A proposito, mi piace il tuo utilizzo TimeUnitdell'API :)

Ecco un po 'di codice di prova:

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

Produzione:

01:00:00

Mi sono reso conto che il mio codice sopra può essere notevolmente semplificato utilizzando una divisione del modulo anziché la sottrazione:

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

Utilizza ancora l' TimeUnitAPI per tutti i valori magici e fornisce esattamente lo stesso output.


2
Amen, come il modo in cui usi l'API TimeUnit :)
Dheeraj Bhaskar il

2
Non è una buona idea reinventare la ruota! La risposta di Triton Man è la soluzione migliore.
محمدباقر,

5
@ محمدباقر Ma l'altra risposta utilizza una libreria esterna, mentre il mio codice utilizza solo il core JDK. Dipende dalle tue esigenze, ad esempio potresti non essere in grado di utilizzare una libreria esterna. L'altra risposta è buona però.
Boemia

2
@Ozuf aggiungi .replaceAll("^00:", "")o .replaceAll("^00:(00:)?", "")per rimuovere minuti e ore se entrambi sono zero.
Boemo

2
@Ozuf ottieni "15:00"e "10:00:23"rispettivamente; solo leader zeri vengono rimossi, a causa della partita essendo ancorata ad iniziare dell'input da ^.
Boemo

77

Il metodo generico per questo è abbastanza semplice:

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

2
@KarenAnne. Dipende se vuoi, ad esempio, "03:59:59" o "3:59:59".
Stephen Hosking,

2
Il tempo è in millisecondi, devi moltiplicare i secondi per 1000
Apurva

5
l'autore ha chiesto di millisecondi, non di secondi!
user924

59

Se stai usando i comuni di Apache:

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

4
Scorciatoia:DurationFormatUtils.formatDurationHMS(timeInMS);
Aroniaina,

@Jorgesys Perché sono obsoleti?
Piovezan,

non sono obsoleti.
Triton Man,

26

Ho usato questo:

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

Vedi la descrizione della classe Formatter .

Vedere l' esempio eseguibile mediante input di 2400 ms.


Non sembra lavorare, semplicemente provarlo by-pass 100, 1000, 1200 e rispondendo come 05:30:00 , 05:30:01 , 05:30:01 .
CoDe

2
@CoDe, funziona per il tuo fuso orario. Devi trovarti in un fuso orario diverso da quello UTC. String.format()è fuso dipendente . La risposta corretta ideale, tuttavia, dovrebbe essere indipendente dal fuso orario .
Derek Mahar,

@CoDe, mostra orari corrispondenti al tuo fuso orario che devono essere diversi da UTC. String.format()è fuso dipendente . La risposta corretta ideale, tuttavia, dovrebbe essere indipendente dal fuso orario .
Derek Mahar,

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

Vedere l' esempio eseguibile mediante input di 1200 ms.


3
Ciò produrrebbe risultati errati per periodi di tempo superiori a un giorno. Avrebbe il numero di ore compreso tra 23 e 0, il che probabilmente qui non è desiderabile.
Kenster,

Nessun amico ... Penso che funzionerebbe ancora allo stesso modo. prova con la data odierna
Vinay Lodha,

1
SimpleDateFormat sdf = new SimpleDateFormat ("hh: mm aa"); nel caso in cui qualcuno desideri in formato 12 ore con am / pm
Ajji


10

Risultati dei test per le 4 implementazioni

Dover fare un sacco di formattazione per dati enormi, è necessaria la migliore prestazione, quindi ecco i risultati (sorprendenti):

per (int i = 0; i <1000000; i ++) {FUNCTION_CALL}

durate:

  • combinazione Materiale : 196 millis
  • formatDurata: 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(); 
     }

quanto sono affidabili queste metriche? Non ho mai veramente capito il processo.
martedì

Nella mia situazione in cui alcune migliaia di oggetti vengono creati in successione, questo test penso sia abbastanza utile. Va bene non impostare solo alcune stringhe, ma creare oggetti che hanno un campo una stringa formattata.
Marius:

@marius ti sei preso la briga di usare StringBuilderpoi fai l'errore di usare "0" + numero tipo di "rovine". Il GC di @mre JVM è estremamente bravo nell'allocare e collezionare molti oggetti di breve durata, senza preoccupazioni. Sono andato con String.formatnessuna logica zero iniziale da affrontare.
escape-llc

7

questo ha funzionato per me, con 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"
            }
        }
    }

Ha funzionato perfettamente per me. Questa dovrebbe essere la risposta migliore poiché gestisce zero ore
vProssimo

6

Seguendo la risposta di Bohemian, non è necessario utilizzare TimeUnit per trovare un valore noto. Sarebbe un codice molto più ottimale

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

Spero che sia d'aiuto


Mi piace di più la tua risposta! Solo semplice matematica. A proposito nel mio caso ho aggiunto i millisecondi alla fine in millisLeft%1000/10modo da ottenere il formatohour:minutes:seconds:milliseconds
Lê Quang Duy

@ LêQuangDuy ho bisogno di millisecondi a 3 cifre come 01: 24: 51,123 ma alla fine stai tagliando 3 cosa fare?
naanu

@naanu basta usaremillisLeft%1000
Lê Quang Duy il

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
}

La risposta dipende dal fuso orario, il che significa che il risultato sarà diverso quando eseguito in diversi fusi orari.
Derek Mahar,

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

Questo stampa:

01:00:00

Stai facendo bene nel lasciare che i metodi della libreria eseguano le conversioni coinvolte per te. java.time, la moderna API di data e ora di Java, o più precisamente, la sua Durationclasse lo fa in modo più elegante e in un modo meno soggetto a errori rispetto aTimeUnit .

Il toMinutesPartetoSecondsPart metodi che ho usato sono stati introdotti in Java 9.

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

L'output è lo stesso di sopra.

Domanda: come può funzionare in Java 6 e 7?

  • In Java 8 e versioni successive e su dispositivi Android più recenti (dal livello API 26, mi hanno detto) java.time è integrato.
  • In Java 6 e 7 ottieni il ThreeTen Backport, il backport delle classi moderne (ThreeTen per JSR 310; vedi i link in basso).
  • Su (vecchi) Android usa l'edizione Android di ThreeTen Backport. Si chiama ThreeTenABP. E assicurati di importare le classi di data e ora org.threeten.bpcon i pacchetti secondari.

link


5

Il codice seguente esegue la conversione in entrambi i modi

23: 59: 58: da 999 a 86398999

e poi

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

Ho votato a favore di questa soluzione. Basta mettere un punto tra sec e mls. E non so perché la gestione di orari e date sia così difficile in Java. Le funzioni più utilizzate dovrebbero essere già disponibili e parte della classe.
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)));

Formato: 00: 00: 00.000

Esempio: 615605 millisecondi

00: 10: 15,605


5

La risposta contrassegnata come corretta ha un piccolo errore,

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

per esempio questo è un esempio del valore che ottengo:

417474:44:19

Questa è la soluzione per ottenere il formato giusto è:

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

ottenendo di conseguenza un formato corretto:

18:44:19

altra opzione per ottenere il formato hh:mm:ssè solo:

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

4

Ho provato come mostrato nella prima risposta. Funziona, ma meno mi ha confuso. La mia risposta di 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

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

dove, milSecsè millisecondi


1

Bene, potresti provare qualcosa del genere:

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

per convertire i millisecondi in un valore temporale

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.