Je veux enregistrer l'heure à l'aide de System.currentTimeMillis()
lorsqu'un utilisateur commence quelque chose dans mon programme. Quand il aura fini, je soustrais la System.currentTimeMillis()
actuelle 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 que ce n'est pas susceptible de prendre quelqu'un une heure.
Quelle est la meilleure façon de faire cela?
Utilisez la classe 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))
);
Remarque: 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 pour les valeurs 0 à 9, procédez comme suit:
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 (par exemple sous 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 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());
}
long time = 1536259;
return (new SimpleDateFormat("mm:ss:SSS")).format(new Date(time));
Impressions:
25: 36: 259
Uhm ... combien de millisecondes sont en une seconde? Et dans une minute? La division n'est pas si 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.
Utilisation de package Java.time 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 format de durée ISO 8601 : PT1M3.553S
(1 minute et 3,553 secondes).
Je ne tirerais pas la dépendance supplémentaire juste pour ça (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 .
Soit des divisions de la main, soit utilisez = 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)));
Éditer par Bombe: Il a été montré dans les commentaires que cette approche ne fonctionne que pour des durées plus courtes (c'est-à-dire moins d'un jour ).
Juste pour ajouter plus d’informations 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 compris cela
Je pense que le meilleur moyen 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 également des fuseaux horaires.
System.out.printf("%tT", millis-TimeZone.getDefault().getRawOffset());
Quelles sorties par exemple:
00:18:32
Explication:
%tT
est l'heure formatée pour l'horloge de 24 heures sous la forme %tH:%tM:%tS
.
%tT
accepte également les longs en tant qu'entrée, il n'est donc pas nécessaire de créer un Date
name__. printf()
imprimera 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 sous la forme String
name__, 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 car la partie jour n'est pas incluse dans la sortie.
Utilisation de 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));
En revisitant la contribution de @ brent-nash, nous pourrions utiliser la fonction modulus au lieu des soustractions et utiliser la méthode String.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);
}
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);
}
Bonne codage :)
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))
Pour les petits moments, 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);
}
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
C’est plus facile avec Java 9:
Duration elapsedTime = Duration.ofMillis(millisDiff );
String humanReadableElapsedTime = String.format(
"%d hours, %d mins, %d seconds",
elapsedTime.toHours(),
elapsedTime.toMinutesPart(),
elapsedTime.toSecondsPart());
Ceci produit une chaîne comme 0 hours, 39 mins, 9 seconds
.
Si vous voulez arrondir à quelques secondes avant le formatage:
elapsedTime = elapsedTime.plusMillis(500).truncatedTo(ChronoUnit.SECONDS);
Pour laisser 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());
}
Nous pouvons maintenant avoir par exemple 39 mins, 9 seconds
.
Pour imprimer les minutes et les secondes précédées du zéro pour les faire toujours en 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());
Nous pouvons maintenant avoir par exemple 0 hours, 39 mins, 09 seconds
.
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());
}
pour les chaînes correctes ("1 heure, 3 secondes", "3 minutes" mais pas "0 heure, 0 minutes, 3 secondes"), 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 couvert cela dans un 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 déterminer comment internationaliser ces données en fonction des paramètres régionaux cibles.
Utilisez Java.util.concurrent.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));
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
Cette réponse est similaire à certaines réponses ci-dessus. Cependant, j'estime que cela serait bénéfique car, contrairement à d'autres réponses, cela supprimera toute virgule ou tout espace supplémentaire et gérera 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);
}
Il ya un problème. Lorsque millisecondes est égal à 59999, il s'agit en réalité d'une minute, mais la durée calculée est de 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);
}
J'ai modifié la réponse de @MyKuLLSKI et ajouté le support de plurlization 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" : "");
}