我想使用System.currentTimeMillis()记录用户在程序中开始某项操作时的时间。当他完成时,我将从start变量中减去当前的System.currentTimeMillis(),并且我希望使用人类可读的格式显示他们所经过的时间,例如“XX小时,XX分钟,XX秒”,甚至“XX分钟,XX秒”,因为它不太可能花费某人一个小时。
最好的方法是什么?
我想使用System.currentTimeMillis()记录用户在程序中开始某项操作时的时间。当他完成时,我将从start变量中减去当前的System.currentTimeMillis(),并且我希望使用人类可读的格式显示他们所经过的时间,例如“XX小时,XX分钟,XX秒”,甚至“XX分钟,XX秒”,因为它不太可能花费某人一个小时。
最好的方法是什么?
当前回答
对于一小时以内的小时间,我更喜欢:
long millis = ...
System.out.printf("%1$TM:%1$TS", millis);
// or
String str = String.format("%1$TM:%1$TS", millis);
对于较长的间隔:
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);
}
其他回答
使用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...
这个主题已经被很好地覆盖了,我只是想分享我的函数,也许你可以使用这些函数,而不是导入整个库。
public long getSeconds(ms) {
return (ms/1000%60);
}
public long getMinutes(ms) {
return (ms/(1000*60)%60);
}
public long getHours(ms) {
return ((ms/(1000*60*60))%24);
}
嗯……一秒是多少毫秒?一分钟后呢?除法没那么难。
int seconds = (int) ((milliseconds / 1000) % 60);
int minutes = (int) ((milliseconds / 1000) / 60);
这样持续几小时、几天、几周、几个月、一年、几十年,等等。
这在Java 9中更容易:
Duration elapsedTime = Duration.ofMillis(millisDiff );
String humanReadableElapsedTime = String.format(
"%d hours, %d mins, %d seconds",
elapsedTime.toHours(),
elapsedTime.toMinutesPart(),
elapsedTime.toSecondsPart());
这将生成像0小时39分9秒这样的字符串。
如果你想在格式化前舍入整秒:
elapsedTime = elapsedTime.plusMillis(500).truncatedTo(ChronoUnit.SECONDS);
如果小时数为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());
}
现在我们有39分9秒。
要打印前导0的分钟和秒,使它们始终是两个数字,只需在相关的格式说明符中插入02,如下所示:
String humanReadableElapsedTime = String.format(
"%d hours, %02d mins, %02d seconds",
elapsedTime.toHours(),
elapsedTime.toMinutesPart(),
elapsedTime.toSecondsPart());
现在我们有0小时39分09秒。
首先,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"