如何在 Java 中测量经过的时间? [复制]
Posted
技术标签:
【中文标题】如何在 Java 中测量经过的时间? [复制]【英文标题】:How do I measure time elapsed in Java? [duplicate] 【发布时间】:2010-12-18 16:57:39 【问题描述】:我想要这样的东西:
public class Stream
public startTime;
public endTime;
public getDuration()
return startTime - endTime;
同样重要的是,例如,如果 startTime 是 23:00,endTime 是 1:00,则持续时间为 2:00。
在 Java 中使用哪些类型来完成此任务?
【问题讨论】:
可能的重复项:***.com/questions/180158、***.com/questions/567659 和 ***.com/questions/503877。 linked Question 不是重复的。该问题的标题具有误导性。该问题的内容是关于从计算机时钟访问当前时间。答案涉及`System.currentTimeMillis()` 和System.nanoTime()
。这里的这个问题的重点是计算两个时刻之间的经过时间,而不考虑获取当前时间。
【参考方案1】:
如果您从 System.currentTimeMillis()
获取时间戳,那么您的时间变量应该是 longs。
【讨论】:
【参考方案2】:Java 提供了静态方法System.currentTimeMillis()
。这会返回一个长值,所以它是一个很好的参考。许多其他类也接受一个很长的“timeInMillis”参数。
而且很多人发现使用Joda Time 库来计算日期和时间更容易。
【讨论】:
+1 用于提及 joda 时间。将它移植到java中发生了什么? jsr310? @Bedwyr:不幸的是,它还没有完成。也许是 Java8。 @BalusC 嗯——也许他们现在可以抽出时间,现在关闭了,一切都被推迟了。【参考方案3】:你的新班级:
public class TimeWatch
long starts;
public static TimeWatch start()
return new TimeWatch();
private TimeWatch()
reset();
public TimeWatch reset()
starts = System.currentTimeMillis();
return this;
public long time()
long ends = System.currentTimeMillis();
return ends - starts;
public long time(TimeUnit unit)
return unit.convert(time(), TimeUnit.MILLISECONDS);
用法:
TimeWatch watch = TimeWatch.start();
// do something
long passedTimeInMs = watch.time();
long passedTimeInSeconds = watch.time(TimeUnit.SECONDS);
之后,可以将经过的时间转换为您喜欢的任何格式,例如使用日历
问候, 加德
【讨论】:
+1 表示TimeUnit
提及。我不知道它存在(为什么它不在 `java.util' 包中?)
@Oscar 也许 Lea 先生确实认为它是并发 API 的一部分
TimeUnit 从 Java 1.5 开始就存在,但在 Java 1.6 中得到了扩展。这是一个非常有用的枚举
创建该类的好主意。赞一个!【参考方案4】:
如果你更喜欢使用 Java 的 Calendar API,你可以试试这个,
Date startingTime = Calendar.getInstance().getTime();
//later on
Date now = Calendar.getInstance().getTime();
long timeElapsed = now.getTime() - startingTime.getTime();
【讨论】:
坏主意。它比仅以毫秒为单位的时间增加了更多的开销。如果您只需要以毫秒为单位的时间,只需使用System.currentTimeMillis()
,您无需了解时区以及您在Calendar#toString()
中看到的所有内容。
你可能有一点。我不知道这是否会对性能产生可衡量的影响,但这可能是一种很好的做法。但是,如果您已经有一个 Calendar 对象,或者如果您想进行更复杂的 Calendar 操作,那么这种方法可能是有效的。【参考方案5】:
在 Java 中使用哪些类型来完成此任务?
答案:长
public class Stream
public long startTime;
public long endTime;
public long getDuration()
return endTime - startTime;
// I would add
public void start()
startTime = System.currentTimeMillis();
public void stop()
endTime = System.currentTimeMillis();
用法:
Stream s = ....
s.start();
// do something for a while
s.stop();
s.getDuration(); // gives the elapsed time in milliseconds.
这是我对您的第一个问题的直接回答。
对于最后一个“注释”,我建议您使用 Joda Time。它包含一个适合您需要的interval 类。
【讨论】:
System.currentTimeMillis() 返回当前时间与 1970 年 1 月 1 日 UTC 午夜之间的差异,以毫秒为单位。 :) 我想我没问题;我担心如果昨天开始,今天停止,我会遇到问题。 很高兴看到 @ChuckNorris 使用 ***。【参考方案6】:在 Java 中使用哪些类型来完成此任务?
简短的回答是long
。现在,更多关于如何测量...
System.currentTimeMillis()
“传统”的做法确实是使用System.currentTimeMillis()
:
long startTime = System.currentTimeMillis();
// ... do something ...
long estimatedTime = System.currentTimeMillis() - startTime;
o.a.c.l.t.StopWatch
请注意,Commons Lang 有一个 StopWatch 类,可用于测量执行时间(以毫秒为单位)。它具有split()
、suspend()
、resume()
等方法方法,允许在执行的不同点进行测量,您可能会觉得方便。看看吧。
System.nanoTime()
如果您正在寻找经过时间的极其精确的测量值,您可能更喜欢使用System.nanoTime()
。从它的javadoc:
long startTime = System.nanoTime();
// ... the code being measured ...
long estimatedTime = System.nanoTime() - startTime;
火腿
另一种选择是使用JAMon,这是一个收集统计数据(执行时间、命中次数、平均执行时间、最小值、最大值等)的工具,用于在开始之间的任何代码() 和 stop() 方法。下面,一个非常简单的例子:
import com.jamonapi.*;
...
Monitor mon=MonitorFactory.start("myFirstMonitor");
...Code Being Timed...
mon.stop();
查看 www.javaperformancetunning.com 上的 this article 以获得很好的介绍。
使用 AOP
最后,如果您不想通过这些度量来弄乱您的代码(或者如果您无法更改现有代码),那么 AOP 将是一个完美的武器。我不会深入讨论这个问题,但我至少想提一下。
下面是一个使用 AspectJ 和 JAMon 的非常简单的切面(这里,切入点的简称将用于 JAMon 监视器,因此调用thisJoinPoint.toShortString()
):
public aspect MonitorAspect
pointcut monitor() : execution(* *.ClassToMonitor.methodToMonitor(..));
Object arround() : monitor()
Monitor monitor = MonitorFactory.start(thisJoinPoint.toShortString());
Object returnedObject = proceed();
monitor.stop();
return returnedObject;
切入点定义可以很容易地适应基于类名、包名、方法名或这些的任何组合来监视任何方法。测量确实是 AOP 的完美用例。
【讨论】:
【参考方案7】:如果您正在编写一个必须处理持续时间的应用程序,那么请查看 Joda-Time,它具有专门用于处理持续时间、Intervals 和期间的类。您的 getDuration()
方法看起来可以返回 Joda-Time Interval:
DateTime start = new DateTime(2004, 12, 25, 0, 0, 0, 0);
DateTime end = new DateTime(2005, 1, 1, 0, 0, 0, 0);
public Interval getInterval()
Interval interval = new Interval(start, end);
【讨论】:
【参考方案8】:如果目的只是将粗略的计时信息打印到程序日志中,那么 Java 项目的简单解决方案不是编写自己的秒表或计时器类,而只需使用 Apache Commons 中的 org.apache.commons.lang.time.StopWatch
类朗。
final StopWatch stopwatch = new StopWatch();
stopwatch.start();
LOGGER.debug("Starting long calculations: ", stopwatch);
...
LOGGER.debug("Time after key part of calcuation: ", stopwatch);
...
LOGGER.debug("Finished calculating ", stopwatch);
【讨论】:
大多数记录器还支持时间戳作为记录输出的一部分。 @詹姆斯麦克马洪。是的,但这些时间戳显示的是当前时间,而不是给定任务的累积时间。 请注意,StopWatch 在其实现中使用 System.currentTimeMillis()。System.currentTimeMillis()
仅适用于 getStartTime()
属性。时间计算完全基于System.nanoTime()
(至少在org.apache.commons.lang3
版本中)【参考方案9】:
值得注意的是
System.currentTimeMillis() 最多只有毫秒精度。在某些 Windows 系统上,它的价值可能是 16 毫秒。它的成本低于替代品 System.nanoTime() 在大多数系统上仅精确到微秒,在 Windows 系统上可以跳转 100 微秒(即有时它不像看起来那么精确) 日历是一种非常昂贵的计算时间的方法。 (除了 XMLGregorianCalendar,我可以想到)有时它是最合适的解决方案,但请注意,您应该只设置较长的时间间隔。【讨论】:
什么是 16ms 和 Windows? Windows 每 16 毫秒读取一次系统时钟? @KorayTugay 旧版本的 Windows 使用时钟频率为 60 Hz 或大约每 16.7 毫秒。我认为它也用于采样在键盘上按下了哪些键。【参考方案10】:很遗憾,到目前为止发布的十个答案中没有一个是完全正确的。
如果您正在测量经过的时间,并且希望它正确,则必须使用System.nanoTime()
。你不能使用System.currentTimeMillis()
,除非你不介意你的结果是错误的。
nanoTime
的目的是测量经过时间,currentTimeMillis
的目的是测量挂钟时间。您不能将其中一个用于其他目的。原因是没有计算机的时钟是完美的。它总是漂移,偶尔需要纠正。这种更正可能是手动进行的,或者在大多数机器的情况下,有一个进程在运行并不断地对系统时钟(“挂钟”)进行小幅更正。这些往往会经常发生。每当有闰秒时,就会发生另一种这样的修正。
由于nanoTime
的目的是测量经过的时间,它不受任何这些小修正的影响。这是你想要使用的。当前与currentTimeMillis
进行的任何时间安排都将被取消——甚至可能是负面的。
您可能会说,“这听起来好像并没有那么重要”,我说,也许不是,但总的来说,正确的代码不比不正确的代码更好吗?此外,nanoTime
无论如何都更短。
之前发布的关于nanoTime
通常只有微秒精度的免责声明是有效的。此外,调用可能需要超过一微秒的时间,具体取决于具体情况(其他情况也是如此),因此不要期望正确计时非常小的时间间隔。
【讨论】:
实际上我需要测量几分钟甚至近一个小时的持续时间,类似这样,在纳米时间和当前毫秒之间是否存在任何性能问题? @entropy - 当然;基本上,某些版本的 OS/Java/CPU 上的 nanoTime 的一些实现将使用硬件 CPU 时间戳计数器 (TSC)。但是,此 TSC 在内核/处理器之间可能不同。如果您的线程在中途被重新安排到不同的核心,您最终会得到来自核心 1 的开始时间戳和来自核心 2 的结束时间戳,但它们可能不是同一时间(您甚至可以得到负值) - 一些示例: ***.com/questions/510462/… 是个好电子 @Brett 是的,完全正确 - 使用它,因此要警惕它的误导性反应。简单的方法是在大量运行中平均结果。 @YuvalA。不!永远不要那样做!甚至不要除以 1000000(这至少在概念上是正确的)。始终使用库,例如 JDK 的TimeUnit.NANOSECONDS.toMillis(value)
。
因为它很容易出错(如评论所示)并且更难阅读。【参考方案11】:
tl;博士
例如,如果 startTime 为 23:00,endTime 为 1:00,则持续时间为 2:00。
不可能。如果您只有一天中的时间,则时钟会在午夜停止。如果没有日期的上下文,我们怎么知道您是指第二天、下周还是下一个十年的凌晨 1 点?
因此,从晚上 11 点到凌晨 1 点意味着时间向后移动 22 小时,逆时针转动时钟的指针。请参阅下面的结果,否定 22 小时。
Duration.between( // Represent a span of time a total number of seconds plus a fractional second in nanoseconds.
LocalTime.of( 23 , 0 ) , // A time-of-day without a date and without a time zone.
LocalTime.of( 1 , 0 ) // A time-of-day clock stops at midnight. So getting to 1 AM from 11 PM means going backwards 22 hours.
) // Return a `Duration` object.
.toString() // Generate a `String` representing this span of time using standard ISO 8601 format: PnYnMnDTnHnMnS
PT-22H
除了时间之外,跨越午夜还需要更大的日期上下文(见下文)。
如何在 Java 中测量经过的时间?
-
使用
Instant.now()
捕捉UTC 中的当前时刻。
稍后再拍摄一个这样的时刻。
将两者都传递给Duration.between
。
(a) 从生成的 Duration
对象中,通过调用各种 to…Part
方法,提取 24 小时天数、小时、分钟、秒和小数秒(以纳秒为单位)。(b) 或, 调用toString
在standard ISO 8601 format 的PnYnMnDTnHnMnS
中生成一个String
。
示例代码,使用一对 Instant
对象。
Duration.between( // Represent a span of time a total number of seconds plus a fractional second in nanoseconds.
then , // Some other `Instant` object, captured earlier with `Instant.now()`.
Instant.now() // Capture the current moment in UTC with a resolution as fine as nanoseconds, depending on the limits of your host computer hardware clock and operating system. Generally you will get current moment in microseconds (six decimal digits of fractional second) in Java 9, 10, and 11, but only milliseconds in Java 8.
) // Return a `Duration` object.
.toString() // Generate a `String` representing this span of time using standard ISO 8601 format: PnYnMnDTnHnMnS
PT3M27.602197S
Java 8+ 中的新技术
我们现在在 Java 8 及更高版本中内置了这方面的新技术,java.time 框架。
java.time
java.time 框架由JSR 310 定义,灵感来自非常成功的Joda-Time 项目,由ThreeTen-Extra 项目扩展,并在Oracle Tutorial 中进行了描述。
Java.util.Date/.Calendar 等旧的日期时间类与 Java 的最早版本捆绑在一起,已被证明设计不佳、令人困惑和麻烦。它们被 java.time 类所取代。
分辨率
其他答案讨论解决方案。
java.time 类具有nanosecond 分辨率,最多为一秒的十进制小数的九位。例如,2016-03-12T04:29:39.123456789Z
。
旧的 java.util.Date/.Calendar 类和 Joda-Time 类都具有毫秒分辨率(3 位小数)。例如,2016-03-12T04:29:39.123Z
。
在 Java 8 中,由于遗留问题,当前时刻的获取分辨率最高仅为毫秒。在 Java 9 及更高版本中,如果您的计算机的硬件时钟运行良好,则当前时间可以被确定为纳秒级分辨率。
时间
如果您真的只想使用缺少任何日期或时区的时间,请使用 LocalTime
类。
LocalTime sooner = LocalTime.of ( 17, 00 );
LocalTime later = LocalTime.of ( 19, 00 );
Duration
表示时间跨度,它以秒数加上纳秒数表示。
Duration duration = Duration.between ( sooner, later );
转储到控制台。
System.out.println ( "sooner: " + sooner + " | later: " + later + " | duration: " + duration );
较早:17:00 |稍后:19:00 |持续时间:PT2H
ISO 8601
注意Duration::toString
的默认输出是标准ISO 8601 格式。在这种格式中,P
标志着开始(如“期间”),T
将任何年-月-日部分与小时-分钟-秒部分分开。
穿越午夜
不幸的是,只有当您绕着时钟穿过午夜时,处理时间才会变得棘手。 LocalTime
类通过假设您想回到当天的早些时候来处理这个问题。
使用与上述相同的代码,但从 23:00
变为 01:00
会导致负 22 小时 (PT-22H
)。
LocalTime sooner = LocalTime.of ( 23, 0 );
LocalTime later = LocalTime.of ( 1, 0 );
更早:23:00 |稍后:01:00 |持续时间:PT-22H
日期时间
如果您打算跨过午夜,那么使用日期时间值而不是仅时间值可能对您来说是有意义的。
时区
时区对于日期至关重要。因此,我们指定了三个项目:(1) 所需日期,(2) 所需时间,以及 (3) 时区作为解释该日期和时间的上下文。这里我们随意选择Montréal区域的时区。
如果您仅通过 offset-from-UTC 定义日期,请使用 ZoneOffset
和 OffsetDateTime
。如果您有一个完整的时区(偏移量加上处理异常情况的规则,例如夏令时),请使用 ZoneId
和 ZonedDateTime
。
LocalDate localDate = LocalDate.of ( 2016, 1, 23 );
ZoneId zoneId = ZoneId.of ( "America/Montreal" );
ZonedDateTime sooner = ZonedDateTime.of ( localDate, LocalTime.of ( 23, 0 ), zoneId );
我们指定较晚的时间为第二天凌晨 1:00。
ZonedDateTime later = ZonedDateTime.of ( localDate.plusDays ( 1 ), LocalTime.of ( 1, 0 ), zoneId );
我们以与上述相同的方式计算Duration
。现在我们得到了这个问题所期望的两个小时。
Duration duration = Duration.between ( sooner, later );
转储到控制台。
System.out.println ( "sooner: " + sooner + " | later: " + later + " | duration: " + duration );
较早:2016-01-23T23:00-05:00[美国/蒙特利尔] |稍后:2016-01-24T01:00-05:00[美国/蒙特利尔] |持续时间:PT2H
夏令时
如果手头的日期时间涉及夏令时 (DST) 或其他此类异常,java.time 类将根据需要进行调整。阅读课程文档了解详情。
关于java.time
java.time 框架内置于 Java 8 及更高版本中。这些类取代了麻烦的旧 legacy 日期时间类,例如 java.util.Date
、Calendar
和 SimpleDateFormat
。
Joda-Time 项目现在位于maintenance mode,建议迁移到java.time 类。
要了解更多信息,请参阅Oracle Tutorial。并在 Stack Overflow 上搜索许多示例和解释。规格为JSR 310。
您可以直接与您的数据库交换 java.time 对象。使用符合JDBC 4.2 或更高版本的JDBC driver。不需要字符串,不需要java.sql.*
类。
从哪里获得 java.time 类?
Java SE 8、Java SE 9、Java SE 10 及更高版本 内置。 标准 Java API 的一部分,带有捆绑实现。 Java 9 添加了一些小功能和修复。 Java SE 6 和 Java SE 7 ThreeTen-Backport 中的大部分 java.time 功能都向后移植到 Java 6 和 7。 Android java.time 类的 android 捆绑包实现的更高版本。 对于早期的 Android (ThreeTenABP 项目采用 ThreeTen-Backport(如上所述)。见How to use ThreeTenABP…。ThreeTen-Extra 项目通过附加类扩展了 java.time。该项目是未来可能添加到 java.time 的试验场。您可以在这里找到一些有用的类,例如Interval
、YearWeek
、YearQuarter
和more。
【讨论】:
这个答案看起来像是 - ***.com/questions/32437550/… 的大部分复制粘贴,虽然它确实提到了时间,但没有回答问题 @Entea 我建议您更仔细地重新阅读。至于复制粘贴,链接的答案没有关于分辨率的部分,没有讨论Duration
,也没有解释诸如夏令时被仅时间计算忽略的异常情况。至于不在这里解决问题,我会说Duration.between ( sooner, later )
结合对午夜滚动问题的解释是对询问“如果 startTime 是 23:00 和 endTime 1:00 来获得持续时间的现场回答2:00”。虽然我很欣赏建设性的批评,但我期待更多的努力。
我已经听从了您的建议,并更仔细地重新阅读了答案。它确实回答了这个问题。通过阅读前 2-3 段并没有找到与该问题的很多联系,我过早地得出结论。这是我的错误,我为我之前的评论道歉。我想知道这里是否有建设性的评论:可以通过以从所问问题本身开始的方式对其进行重组来改进答案。段落可以按抽象的降序排列,也许是从一般回答“如何测量经过的时间”开始,然后进入细节
@Entea 道歉接受。根据您的评论,我在顶部添加了一个“tl;dr”部分,该部分直接指向问题的重点,并提供了计算经过时间的错误方式和正确方式的实际代码示例。对这个答案的改进很好。感谢您的建议。
感谢您花时间回答我的 cmets。我学到了一个很好的教训,一个起初看起来含糊不清的论文不应该被完全拒绝,因为它实际上可能包含有效的观点。这可能是人们在需要有效沟通时必须学习的一般规则。【参考方案12】:
我发现这段代码在计时时很有用:
public class Et
public Et()
reset();
public void reset()
t0=System.nanoTime();
public long t0()
return t0;
public long dt()
return System.nanoTime()-t0();
public double etms()
return etms(dt());
@Override public String toString()
return etms()+" ms.";
public static double etms(long dt)
return dt/1000000.; // 1_000_000. breaks cobertura
private Long t0;
【讨论】:
【参考方案13】:使用这个:
SimpleDateFormat format = new SimpleDateFormat("HH:mm");
Date d1 = format.parse(strStartTime);
Date d2 = format.parse(strEndTime);
long diff = d2.getTime() - d1.getTime();
long diffSeconds,diffMinutes,diffHours;
if (diff > 0)
diffSeconds = diff / 1000 % 60;
diffMinutes = diff / (60 * 1000) % 60;
diffHours = diff / (60 * 60 * 1000);
else
long diffpos = (24*((60 * 60 * 1000))) + diff;
diffSeconds = diffpos / 1000 % 60;
diffMinutes = diffpos / (60 * 1000) % 60;
diffHours = (diffpos / (60 * 60 * 1000));
(同样重要的是,例如,如果 startTime 为 23:00,endTime 为 1:00,则持续时间为 2:00。)
“else”部分可以正确处理
【讨论】:
【参考方案14】:Byte Stream Reader Elapsed Time for 23.7 MB is 96 secs
import java.io.*;
import java.io.IOException;
import java.util.Scanner;
class ElaspedTimetoCopyAFileUsingByteStream
private long startTime = 0;
private long stopTime = 0;
private boolean running = false;
public void start()
this.startTime = System.currentTimeMillis();
this.running = true;
public void stop()
this.stopTime = System.currentTimeMillis();
this.running = false;
public long getElapsedTime()
long elapsed;
if (running)
elapsed = (System.currentTimeMillis() - startTime);
else
elapsed = (stopTime - startTime);
return elapsed;
public long getElapsedTimeSecs()
long elapsed;
if (running)
elapsed = ((System.currentTimeMillis() - startTime) / 1000);
else
elapsed = ((stopTime - startTime) / 1000);
return elapsed;
public static void main(String[] args) throws IOException
ElaspedTimetoCopyAFileUsingByteStream s = new ElaspedTimetoCopyAFileUsingByteStream();
s.start();
FileInputStream in = null;
FileOutputStream out = null;
try
in = new FileInputStream("vowels.txt"); // 23.7 MB File
out = new FileOutputStream("output.txt");
int c;
while ((c = in.read()) != -1)
out.write(c);
finally
if (in != null)
in.close();
if (out != null)
out.close();
s.stop();
System.out.println("elapsed time in seconds: " + s.getElapsedTimeSecs());
[Elapsed Time for Byte Stream Reader][1]
**Character Stream Reader Elapsed Time for 23.7 MB is 3 secs**
import java.io.*;
import java.io.IOException;
import java.util.Scanner;
class ElaspedTimetoCopyAFileUsingCharacterStream
private long startTime = 0;
private long stopTime = 0;
private boolean running = false;
public void start()
this.startTime = System.currentTimeMillis();
this.running = true;
public void stop()
this.stopTime = System.currentTimeMillis();
this.running = false;
public long getElapsedTime()
long elapsed;
if (running)
elapsed = (System.currentTimeMillis() - startTime);
else
elapsed = (stopTime - startTime);
return elapsed;
public long getElapsedTimeSecs()
long elapsed;
if (running)
elapsed = ((System.currentTimeMillis() - startTime) / 1000);
else
elapsed = ((stopTime - startTime) / 1000);
return elapsed;
public static void main(String[] args) throws IOException
ElaspedTimetoCopyAFileUsingCharacterStream s = new ElaspedTimetoCopyAFileUsingCharacterStream();
s.start();
FileReader in = null; // CharacterStream Reader
FileWriter out = null;
try
in = new FileReader("vowels.txt"); // 23.7 MB
out = new FileWriter("output.txt");
int c;
while ((c = in.read()) != -1)
out.write(c);
finally
if (in != null)
in.close();
if (out != null)
out.close();
s.stop();
System.out.println("elapsed time in seconds: " + s.getElapsedTimeSecs());
[Elapsed Time for Character Stream Reader][2]
[1]: https://i.stack.imgur.com/hYo8y.png
[2]: https://i.stack.imgur.com/xPjCK.png
【讨论】:
【参考方案15】:我根据我偷走的东西构建了一个格式化函数。我需要一种在日志消息中“分析”内容的方法,因此我需要一个固定长度的持续时间消息。
public static String GetElapsed(long aInitialTime, long aEndTime, boolean aIncludeMillis)
StringBuffer elapsed = new StringBuffer();
Map<String, Long> units = new HashMap<String, Long>();
long milliseconds = aEndTime - aInitialTime;
long seconds = milliseconds / 1000;
long minutes = milliseconds / (60 * 1000);
long hours = milliseconds / (60 * 60 * 1000);
long days = milliseconds / (24 * 60 * 60 * 1000);
units.put("milliseconds", milliseconds);
units.put("seconds", seconds);
units.put("minutes", minutes);
units.put("hours", hours);
units.put("days", days);
if (days > 0)
long leftoverHours = hours % 24;
units.put("hours", leftoverHours);
if (hours > 0)
long leftoeverMinutes = minutes % 60;
units.put("minutes", leftoeverMinutes);
if (minutes > 0)
long leftoverSeconds = seconds % 60;
units.put("seconds", leftoverSeconds);
if (seconds > 0)
long leftoverMilliseconds = milliseconds % 1000;
units.put("milliseconds", leftoverMilliseconds);
elapsed.append(PrependZeroIfNeeded(units.get("days")) + " days ")
.append(PrependZeroIfNeeded(units.get("hours")) + " hours ")
.append(PrependZeroIfNeeded(units.get("minutes")) + " minutes ")
.append(PrependZeroIfNeeded(units.get("seconds")) + " seconds ")
.append(PrependZeroIfNeeded(units.get("milliseconds")) + " ms");
return elapsed.toString();
private static String PrependZeroIfNeeded(long aValue)
return aValue < 10 ? "0" + aValue : Long.toString(aValue);
还有一个测试类:
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import junit.framework.TestCase;
public class TimeUtilsTest extends TestCase
public void testGetElapsed()
long start = System.currentTimeMillis();
GregorianCalendar calendar = (GregorianCalendar) Calendar.getInstance();
calendar.setTime(new Date(start));
calendar.add(Calendar.MILLISECOND, 610);
calendar.add(Calendar.SECOND, 35);
calendar.add(Calendar.MINUTE, 5);
calendar.add(Calendar.DAY_OF_YEAR, 5);
long end = calendar.getTimeInMillis();
assertEquals("05 days 00 hours 05 minutes 35 seconds 610 ms", TimeUtils.GetElapsed(start, end, true));
【讨论】:
以上是关于如何在 Java 中测量经过的时间? [复制]的主要内容,如果未能解决你的问题,请参考以下文章