Comment convertir des millisecondes en "X minutes, x secondes" en Java?


Je veux enregistrer l'heure en utilisant System.currentTimeMillis() lorsqu'un utilisateur commence quelque chose dans mon programme. Quand il aura terminé, je soustrairai le courant System.currentTimeMillis() de la variable start, et je veux leur montrer le temps écoulé en utilisant un format lisible par l'homme tel que "XX heures, XX minutes, XX secondes" ou même "XX minutes, XX secondes" car il ne risque pas de prendre une heure à quelqu'un.

Quelle est la meilleure façon de le faire?

Author: Click Upvote, 2009-03-09

25 answers

Utiliser le java.util.concurrent.TimeUnit classe:

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

Remarque: TimeUnit fait partie de la spécification Java 1.5, mais toMinutes a été ajouté à partir de Java 1.6.

Pour ajouter un premier zéro pour les valeurs 0-9, faites simplement:

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

Si TimeUnit ou toMinutes ne sont pas pris en charge (comme sur Android avant la version 9 de l'API), utilisez les équations suivantes:

int seconds = (int) (milliseconds / 1000) % 60 ;
int minutes = (int) ((milliseconds / (1000*60)) % 60);
int hours   = (int) ((milliseconds / (1000*60*60)) % 24);
//etc...
 1094
Author: siddhadev, 2016-09-01 21:52:30

Basé sur la réponse de @siddhadev, j'ai écrit une fonction qui convertit les millisecondes en une chaîne formatée:

   /**
     * 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());
    }
 110
Author: Brent Writes Code, 2018-02-10 22:00:41
long time = 1536259;

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

Imprime:

25:36:259

 59
Author: Damien, 2015-11-03 16:52:51

Euh... combien de millisecondes sont dans une seconde? Et en une minute? La Division n'est pas difficile.

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

Continuez comme ça pendant des heures, des jours, des semaines, des mois, des années, des décennies, peu importe.

 34
Author: Bombe, 2009-03-09 08:42:52

En utilisant le java.paquet de temps dans Java 8:

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

La sortie est au format de durée ISO 8601: PT1M3.553S (1 minute et 3.553 secondes).

 25
Author: Vitalii Fedorenko, 2014-11-29 19:41:53

Je ne voudrais pas extraire la dépendance supplémentaire juste pour cela (la division n'est pas si difficile, après tout), mais si vous utilisez Commons Lang de toute façon, il y a les DurationFormatUtils.

 24
Author: Thilo, 2013-05-06 10:16:50

Soit des divisions à la main, soit utilisez 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)));

Modifier par Bombe: Il a été démontré dans les commentaires que cette approche ne fonctionne que pour des durées plus petites (c.-à-d. moins d'une journée).

 23
Author: cadrian, 2017-05-23 11:54:59

Juste pour ajouter plus d'informations si vous voulez formater comme: HH: mm: ss

0

0

0

Utilisez ceci:

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

Je viens d'avoir ce problème maintenant et j'ai compris

 19
Author: fredcrs, 2011-05-25 16:52:49

Je pense que le meilleur moyen est:

String.format("%d min, %d sec", 
    TimeUnit.MILLISECONDS.toSeconds(length)/60,
    TimeUnit.MILLISECONDS.toSeconds(length) % 60 );
 12
Author: Xtera, 2011-04-06 10:01:52

Solution la plus courte:

Voici probablement le plus court qui traite également des fuseaux horaires.

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

Qui sort par exemple:

00:18:32

Explication:

%tT le temps est formaté pour l'horloge de 24 heures comme %tH:%tM:%tS.

%tT accepte aussi longs que d'entrée, donc pas besoin de créer un Date. {[7] } affichera simplement l'heure spécifiée en millisecondes, mais dans le fuseau horaire actuel, nous devons donc soustraire le décalage brut du fuseau horaire actuel de sorte que 0 millisecondes sera 0 heures et non la valeur de décalage horaire du fuseau horaire actuel.

Note #1: Si vous avez besoin de la raison en tant que String, vous pouvez l'obtenir comme ceci:

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

Remarque # 2: Cela ne donne un résultat correct que si millis est inférieur à un jour car la partie jour n'est pas incluse dans la sortie.

 11
Author: icza, 2016-02-27 16:38:13

Joda-Temps

En utilisant 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));
 6
Author: dogbane, 2014-08-06 18:54:22

Pour Android ci-dessous 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
Author: Pradeep, 2012-07-06 06:39:06

En revisitant la contribution @brent-nash, nous pourrions utiliser la fonction module au lieu des soustractions et utiliser la chaîne.méthode de format pour la chaîne de résultat:

  /**
   * 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);
   }
 5
Author: Jose Tepedino, 2018-02-09 13:17:44

Pour les petits temps, moins d'une heure, je préfère:

long millis = ...

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

Pour des intervalles plus longs:

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);
}
 3
Author: Carlos Heuberger, 2011-04-05 15:49:34
    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
Author: Fathah Rehman P, 2013-07-23 19:26:53

Mon calcul simple:

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

Codage Heureux :)

 3
Author: Shohan Ahmed Sijan, 2017-01-26 20:26:57

Voici une réponse basée sur la réponse de Brent Nash, espérons que cela aide !

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());
}
 2
Author: Reda Bouaichi, 2013-06-25 15:12:09

C'est plus facile dans Java 9:

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

Cela produit une chaîne comme 0 hours, 39 mins, 9 seconds.

Si vous voulez arrondir à des secondes entières avant le formatage:

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

Pour omettre les heures si elles sont 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());
    }

Maintenant, nous pouvons avoir par exemple 39 mins, 9 seconds.

Pour imprimer les minutes et les secondes avec zéro pour les rendre toujours à deux chiffres, il suffit d'insérer 02 dans les spécificateurs de format pertinents, ainsi:

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

Maintenant, nous pouvons avoir par exemple 0 hours, 39 mins, 09 seconds.

 2
Author: Ole V.V., 2018-01-15 10:59:49

Si vous savez que le décalage horaire serait inférieur à une heure, vous pouvez utiliser le code suivant:

    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 en résultera: 51: 00

 1
Author: Gourav Singla, 2014-09-22 11:41:02

Cette réponse est similaire à certaines réponses ci-dessus. Cependant, je pense que ce serait bénéfique car, contrairement à d'autres réponses, cela supprimera toutes les virgules ou espaces supplémentaires et l'abréviation des poignées.

/**
 * 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);
}
 1
Author: Jared Rummler, 2015-03-18 04:20:09

J'ai couvert cela dans une autre réponse mais vous pouvez faire:

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

La sortie est quelque chose comme Map:{DAYS=1, HOURS=3, MINUTES=46, SECONDS=40, MILLISECONDS=0, MICROSECONDS=0, NANOSECONDS=0}, avec les unités commandées.

C'est à vous de comprendre comment internationaliser ces données en fonction des paramètres régionaux cibles.

 1
Author: Sebastien Lorber, 2017-05-23 11:47:28

Utiliser java.util.simultané.TimeUnit, et utilisez cette méthode simple:

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

Par exemple:

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));
 1
Author: Aramis Rodríguez Blanco, 2018-06-04 08:59:04

Il y a un problème. Quand millisecondes est 59999, en fait c'est 1 minute mais il sera calculé comme 59 secondes et 999 millisecondes sont perdues.

Voici une version modifiée basée sur les réponses précédentes, qui peut résoudre cette perte:

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);
}
 1
Author: Hexise, 2018-09-23 14:06:18

Pour corriger des chaînes de caractères ("1 heure, 3sec", "3 min", mais pas "0 h 0 min 3 sec") j'écris ce 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";
 0
Author: John, 2012-02-08 16:06:35

J'ai modifié la réponse de @MyKuLLSKI et ajouté le support de plurlisation. J'ai pris quelques secondes parce que je n'en avais pas besoin, mais n'hésitez pas à le rajouter si vous en avez besoin.

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" : "");
}
 0
Author: bitstream, 2015-07-13 18:47:51