我想使用System.currentTimeMillis()记录用户在程序中开始某项操作时的时间。当他完成时,我将从start变量中减去当前的System.currentTimeMillis(),并且我希望使用人类可读的格式显示他们所经过的时间,例如“XX小时,XX分钟,XX秒”,甚至“XX分钟,XX秒”,因为它不太可能花费某人一个小时。
最好的方法是什么?
我想使用System.currentTimeMillis()记录用户在程序中开始某项操作时的时间。当他完成时,我将从start变量中减去当前的System.currentTimeMillis(),并且我希望使用人类可读的格式显示他们所经过的时间,例如“XX小时,XX分钟,XX秒”,甚至“XX分钟,XX秒”,因为它不太可能花费某人一个小时。
最好的方法是什么?
当前回答
最短的解决方案:
这可能是最短的一个,也涉及到时区。
System.out.printf("%tT", millis-TimeZone.getDefault().getRawOffset());
输出例如:
00:18:32
解释:
%tT是24小时时钟格式为%tH:%tM:%tS的时间。
%tT也接受长时间作为输入,因此不需要创建Date。Printf()将简单地以毫秒为单位打印指定的时间,但在当前时区中,因此我们必须减去当前时区的原始偏移量,以便0毫秒将是0小时,而不是当前时区的时间偏移值。
注意#1:如果你需要一个字符串形式的结果,你可以这样得到它:
String t = String.format("%tT", millis-TimeZone.getDefault().getRawOffset());
注意#2:只有当millis小于一天时,才会给出正确的结果,因为一天部分不包括在输出中。
其他回答
首先,System.currentTimeMillis()和Instant.now()对于计时来说并不理想。它们都报告了挂钟时间,而计算机并不能准确地知道这个时间,而且它可能会不规律地移动,例如,如果NTP守护进程更正了系统时间,就会往回走。如果计时发生在一台机器上,那么应该使用System.nanoTime()。
其次,从Java 8开始,Java .time. duration是表示持续时间的最佳方式:
long start = System.nanoTime();
// do things...
long end = System.nanoTime();
Duration duration = Duration.ofNanos(end - start);
System.out.println(duration); // Prints "PT18M19.511627776S"
System.out.printf("%d Hours %d Minutes %d Seconds%n",
duration.toHours(), duration.toMinutes() % 60, duration.getSeconds() % 60);
// prints "0 Hours 18 Minutes 19 Seconds"
使用java . util . concurrent。TimeUnit,使用这个简单的方法:
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;
}
例如:
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));
使用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))
);
注意:TimeUnit是Java 1.5规范的一部分,但是toMinutes是在Java 1.6中添加的。
为0-9的值添加前导零,只需执行以下操作:
String.format("%02d min, %02d sec",
TimeUnit.MILLISECONDS.toMinutes(millis),
TimeUnit.MILLISECONDS.toSeconds(millis) -
TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(millis))
);
如果TimeUnit或toMinutes不受支持(例如在API版本9之前的Android上),使用以下公式:
int seconds = (int) (milliseconds / 1000) % 60 ;
int minutes = (int) ((milliseconds / (1000*60)) % 60);
int hours = (int) ((milliseconds / (1000*60*60)) % 24);
//etc...
有个问题。当毫秒为59999时,实际上是1分钟,但它将被计算为59秒,损失了999毫秒。
以下是根据之前的答案修改后的版本,可以解决这个损失:
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);
}
我不会为此引入额外的依赖项(毕竟,除法并不那么难),但如果您无论如何都在使用Commons Lang,还有DurationFormatUtils。
用法示例(从这里改编):
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;
}
例子:
long lastTime = System.currentTimeMillis() - 2000;
System.out.println("Elapsed time: " + getAge(lastTime));
//Output: 2s
注意:从两个LocalDateTime对象中获取millis可以使用:
long age = ChronoUnit.MILLIS.between(initTime, LocalDateTime.now())