我想记录System.currentTimeMillis()
用户在程序中开始执行操作所用的时间。当他完成后,我会减去当前System.currentTimeMillis()
从start
变量,我想向他们展示使用人类可读的格式经过诸如“XX小时XX分钟,XX秒”,甚至是“XX分钟,XX秒”的时间,因为它的不太可能花一个小时。
最好的方法是什么?
我想记录System.currentTimeMillis()
用户在程序中开始执行操作所用的时间。当他完成后,我会减去当前System.currentTimeMillis()
从start
变量,我想向他们展示使用人类可读的格式经过诸如“XX小时XX分钟,XX秒”,甚至是“XX分钟,XX秒”的时间,因为它的不太可能花一个小时。
最好的方法是什么?
Answers:
使用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...
int hours = (int) ((milliseconds / (1000*60*60)) % 24)
这行不通!相反,应该像这样int hours = (int) (milliseconds / (1000*60*60)) ;
String.format("%01d:%02d:%02d", hours, minutes, seconds);
基于@siddhadev的答案,我编写了一个函数,该函数将毫秒转换为格式化的字符串:
/**
* 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());
}
1 Days 1 Hours 1 Minutes 1 Seconds
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;
以及String.format方法:return String.format("%d Days %d Hours %d Minutes %d Seconds %d Milliseconds", days, hours, minutes, seconds, milliseconds);
long time = 1536259;
return (new SimpleDateFormat("mm:ss:SSS")).format(new Date(time));
印刷品:
25:36:259
Duration dur = new Duration(start, end);
long millis = dur.getMillis();
DateTimeFormat.forPattern("mm:ss:SSS").print(new DateTime(time));
或将Duration转换为可以使用Joda自动打印的Period PeriodFormatter
。如果不是ISO时间顺序,则转换可能会失去精度。假设一个持续时间由变量表示duration
。 Period period = duration.toPeriod().normalizedStandard(PeriodType.time());
PeriodFormat.getDefault().print(period))
输出结果很棒:1秒和581毫秒,回答了上面的主要问题。
嗯...几秒钟是几毫秒?等一下 划分并不难。
int seconds = (int) ((milliseconds / 1000) % 60);
int minutes = (int) ((milliseconds / 1000) / 60);
像这样继续几个小时,几天,几周,几个月,一年,几十年。
在Java 8中使用java.time包:
Instant start = Instant.now();
Thread.sleep(63553);
Instant end = Instant.now();
System.out.println(Duration.between(start, end));
输出为ISO 8601持续时间格式:PT1M3.553S
(1分钟3.553秒)。
我不会为此而引入额外的依赖关系(毕竟划分并不难),但是无论如何,如果您使用的是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对象获取毫秒,可以使用:
long age = ChronoUnit.MILLIS.between(initTime, LocalDateTime.now())
手动分割,或使用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)));
孟买编辑:注释中显示,此方法仅在较小的持续时间内(即少于一天)有效。
只是要添加更多信息,如果您想要格式化:HH:mm:ss
0 <= HH <=无限
0 <=毫米<60
0 <= ss <60
用这个:
int h = (int) ((startTimeInMillis / 1000) / 3600);
int m = (int) (((startTimeInMillis / 1000) / 60) % 60);
int s = (int) ((startTimeInMillis / 1000) % 60);
我现在刚遇到这个问题,并弄清楚了
我认为最好的方法是:
String.format("%d min, %d sec",
TimeUnit.MILLISECONDS.toSeconds(length)/60,
TimeUnit.MILLISECONDS.toSeconds(length) % 60 );
最短的解决方案:
这可能是最短的,也涉及时区。
System.out.printf("%tT", millis-TimeZone.getDefault().getRawOffset());
哪个输出例如:
00:18:32
说明:
%tT
是24小时制的时间格式为 %tH:%tM:%tS
。
%tT
还接受long作为输入,因此无需创建Date
。printf()
将仅显示以毫秒为单位的指定时间,但是在当前时区中,因此我们必须减去当前时区的原始偏移量,以便0毫秒为0小时,而不是当前时区的时间偏移值。
注意#1:如果需要将结果作为String
,则可以这样获得:
String t = String.format("%tT", millis-TimeZone.getDefault().getRawOffset());
注意#2:仅当millis
少于一天时,这才给出正确的结果,因为输出中不包括日部分。
long millis = 8398;
当我将其传递给String.format("%tT", millis)
我的输出时是19:00:08。19来自哪里?
TimeZone.getDefault().getRawOffset()
,完全如答案中所述:String.format("%tT", millis-TimeZone.getDefault().getRawOffset())
使用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));
回顾@ brent-nash贡献,我们可以使用模函数而不是减法,并对结果字符串使用String.format方法:
/**
* 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);
}
对于少于一小时的时间,我更喜欢:
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);
}
%tH
仅显示0到23小时吗?这意味着例如24小时将显示为00
,而25小时则显示为01
...有效期%tT
-天将被静默丢弃。当然,也可以显示几天,但这对于我写这篇文章时(早在2011年)遇到的问题来说是一个过大的
我的简单计算:
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);
}
快乐的编码:)
这是一个基于Brent Nash答案的答案,希望对您有所帮助!
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());
}
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
diff=diff-(hours*60*1000);
应该是diff=diff-(hours*60*60*1000);
。我尝试对其进行编辑,但是StackOverflow令人讨厌的编辑策略表示该字符不足以进行编辑。
首先,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"
如果您知道时差少于一个小时,那么可以使用以下代码:
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)));
其结果是:51:00
这个答案类似于上面的一些答案。但是,我认为这将是有益的,因为与其他答案不同,这将删除任何多余的逗号或空格并处理缩写。
/**
* 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);
}
这儿存在一个问题。当毫秒为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);
}
在Java 9中,这更容易:
Duration elapsedTime = Duration.ofMillis(millisDiff );
String humanReadableElapsedTime = String.format(
"%d hours, %d mins, %d seconds",
elapsedTime.toHours(),
elapsedTime.toMinutesPart(),
elapsedTime.toSecondsPart());
这产生一个像 0 hours, 39 mins, 9 seconds
。
如果要在格式化前四舍五入为秒:
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 mins, 9 seconds
。
要以分钟零开头打印分钟和秒以使其始终为两位数,只需将其插入02
相关的格式说明符即可,因此:
String humanReadableElapsedTime = String.format(
"%d hours, %02d mins, %02d seconds",
elapsedTime.toHours(),
elapsedTime.toMinutesPart(),
elapsedTime.toSecondsPart());
现在我们可以举个例子0 hours, 39 mins, 09 seconds
。
if
- else
在那里。
对于正确的字符串(“ 1小时3秒”,“ 3分钟”,但不是“ 0小时0分3秒”),我编写以下代码:
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";
我修改了@MyKuLLSKI的答案,并添加了对卷积的支持。我花了几秒钟是因为我不需要它们,但是如果需要可以随时添加它。
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" : "");
}
int intervalMins
vs long millis
我已经在另一个答案中对此进行了介绍,但是您可以执行以下操作:
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;
}
输出类似于Map:{DAYS=1, HOURS=3, MINUTES=46, SECONDS=40, MILLISECONDS=0, MICROSECONDS=0, NANOSECONDS=0}
,有序。
由您决定如何根据目标语言环境对这些数据进行国际化。
使用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));