Comment convertir millisecondes en" X minutes, X secondes " en Java?
je veux enregistrer l'heure en utilisant System.currentTimeMillis()
quand un utilisateur commence quelque chose dans mon programme. Quand il aura terminé, je soustrairai l'actuel 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 " parce qu'il est peu probable de prendre quelqu'un une heure.
Quelle est la meilleure façon de faire cela?
25 réponses
utiliser la 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))
);
Note: TimeUnit
fait partie de la spécification Java 1.5, mais toMinutes
a été ajouté à partir de Java 1.6.
pour ajouter un zéro de tête pour les valeurs 0-9, il suffit de faire:
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...
basé sur la réponse de @siddhadev, j'ai écrit une fonction qui convertit des millisecondes en 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());
}
long time = 1536259;
return (new SimpleDateFormat("mm:ss:SSS")).format(new Date(time));
Imprime:
25:36:259
Uhm... combien de millisecondes sont dans un deuxième? Et en une minute? La Division n'est pas difficile.
int seconds = (int) ((milliseconds / 1000) % 60);
int minutes = (int) ((milliseconds / 1000) / 60);
Continue comme ça pendant des heures, des jours, des semaines, des mois, des années, des décennies, n'importe quoi.
utilisant le java.time package en 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).
Je ne tirerais pas dans 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 le DurationFormatUtils .
deux divisions à la main, ou utiliser le SimpleDateFormat API .
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é montré dans les commentaires que cette approche ne fonctionne que pour des durées plus courtes (c.-à-d. moins d'un jour).
juste pour ajouter plus d'information si vous voulez formater comme: HH: mm: ss
0 <= HH <= infini
0 < = mm < 60
0 < = ss < 60
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 cela
je pense que la meilleure façon est:
String.format("%d min, %d sec",
TimeUnit.MILLISECONDS.toSeconds(length)/60,
TimeUnit.MILLISECONDS.toSeconds(length) % 60 );
solution la plus courte:
Voici probablement le plus court qui traite aussi des fuseaux horaires.
System.out.printf("%tT", millis-TimeZone.getDefault().getRawOffset());
qui affiche par exemple:
00:18:32
explication:
%tT
est l'heure formatée pour l'horloge de 24 heures comme %tH:%tM:%tS
.
%tT
accepte aussi les longs comme entrée, donc pas besoin pour créer un Date
. printf()
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 pour que 0 millisecondes soit 0 heure et non la valeur de décalage horaire du fuseau horaire actuel.
Note #1: Si vous avez besoin du résultat comme un String
, vous pouvez l'obtenir comme ceci:
String t = String.format("%tT", millis-TimeZone.getDefault().getRawOffset());
Note #2: cela ne donne un résultat correct que si millis
est inférieur à un jour parce que la partie de jour n'est pas incluse dans la sortie.
Joda-Time
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));
pour Android sous 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))
revisitant la contribution @brent-nash, nous pourrions utiliser la fonction de module au lieu des soustractions et utiliser la chaîne de caractères.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);
}
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 les 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);
}
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
Mon simple calcul:
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 :)
Voici une réponse basée sur la réponse de Brent Nash, L'espoir qui 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());
}
c'est plus facile en 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 à la seconde entière avant le formatage:
elapsedTime = elapsedTime.plusMillis(500).truncatedTo(ChronoUnit.SECONDS);
pour supprimer 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 minutes et secondes avec zéro en tête pour les faire toujours deux chiffres, il suffit d'insérer 02
dans les spécificateurs de format appropriés, 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
.
si vous savez que le décalage horaire est 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ésulte à: 51: 00
cette réponse est similaire à certaines réponses ci-dessus. Cependant, je pense que ce serait bénéfique parce que, contrairement à d'autres réponses, cela supprimera toute virgule Ou espace supplémentaire et gère l'abréviation.
/**
* 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);
}
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 de la cible locale.
utilisez 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));
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 est perdu.
Voici une version modifiée basée sur des 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);
}
pour cordes correctes ("1hour, 3sec", "3 min" mais pas "0 heure, 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";
j'ai modifié la réponse de @MyKuLLSKI et ajouté le support de plurlization. J'ai pris des secondes parce que je n'en avais pas besoin, mais n'hésitez pas à les 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" : "");
}