301 votos

¿Cómo convertir milisegundos a "x minutos, x segundos" en Java?

Quiero grabar el tiempo usando System.currentTimeMillis() cuando un usuario comienza algo en mi programa. Cuando finalice, restaré el System.currentTimeMillis() actual de la variable start, y quiero mostrarles el tiempo transcurrido usando un formato legible para humanos como "XX horas, XX mins, XX segundos" o incluso "XX mins, XX segundos" porque es poco probable que alguien tarde una hora.

¿Cuál es la mejor manera de hacer esto?

726voto

siddhadev Puntos 6083

Utilice la clase java.util.concurrent.TimeUnit:

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

Nota: TimeUnit forma parte de la especificación de Java 1.5, pero toMinutes se agregó a partir de Java 1.6.

Para agregar un cero inicial a los valores de 0 a 9, simplemente haga lo siguiente:

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

Si TimeUnit o toMinutes no son compatibles (como en Android antes de la versión de API 9), utilice las siguientes ecuaciones:

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

61voto

Brent Nash Puntos 6337

Basado en la respuesta de @siddhadev, escribí una función que convierte milisegundos a una cadena formateada:

   /**
     * Convierte una duración en milisegundos a un formato de cadena
     * 
     * @param millis Una duración para convertir a una forma de cadena
     * @return Una cadena en forma de "X Días Y Horas Z Minutos A Segundos".
     */
    public static String getDurationBreakdown(long millis) {
        if(millis < 0) {
            throw new IllegalArgumentException("¡La duración debe ser mayor que cero!");
        }

        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(" Días ");
        sb.append(hours);
        sb.append(" Horas ");
        sb.append(minutes);
        sb.append(" Minutos ");
        sb.append(seconds);
        sb.append(" Segundos");

        return(sb.toString());
    }

23voto

Bombe Puntos 34185

Uhm... ¿cuántos milisegundos hay en un segundo? ¿Y en un minuto? La división no es tan difícil.

int segundos = (int) ((milisegundos / 1000) % 60);
int minutos = (int) ((milisegundos / 1000) / 60);

Sigue así para horas, días, semanas, meses, años, décadas, lo que sea.

19voto

cadrian Puntos 4102

Ya sea dividir a mano, o usar la API SimpleDateFormat.

long start = System.currentTimeMillis();
// haz tu trabajo...
long elapsed = System.currentTimeMillis() - start;
DateFormat df = new SimpleDateFormat("HH 'horas', mm 'mins,' ss 'segundos'");
df.setTimeZone(TimeZone.getTimeZone("GMT+0"));
System.out.println(df.format(new Date(elapsed)));

Editado por Bombe: Se ha demostrado en los comentarios que este enfoque solo funciona para duraciones más pequeñas (es decir, menos de un día).

18voto

Thilo Puntos 108673

No agregaría la dependencia adicional solo por eso (dividir no es tan difícil, después de todo), pero si ya estás utilizando Commons Lang, existen los DurationFormatUtils.

Ejemplo de uso (adaptado de aquí):

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

Ejemplo:

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

//Salida: 2s

Nota: Para obtener los milisegundos entre dos objetos LocalDateTime puedes utilizar:

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

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by:

X