java中的当前时间(以微秒为单位)

Set*_*eth 98 java timestamp

在Unix系统上,有没有办法在Java中获得具有微秒级精度的时间戳?像C的gettimeofday功能.

AlB*_*lue 142

不,Java没有这种能力.

它确实有System.nanoTime(),但它只是给出了一些先前已知时间的偏移量.因此,虽然您无法从中获取绝对数,但您可以使用它来测量纳秒(或更高)精度.

请注意,JavaDoc表示虽然这提供了纳秒精度,但这并不意味着纳秒精度.因此,取一些适当大的模数的返回值.

  • +1用于区分精度和准确度. (59认同)
  • 在Linux上,System.nanoTime()调用clock_gettime(CLOCK_MONOTONIC,_).[Brian Oxley](http://binkley.blogspot.com/2010/10/java-aint-got-no-rhythm-but-can-it-keep.html)挖掘Java的源代码来找到这个金块. (9认同)
  • 这个答案现在已经过时了**.Java 9的OpenJDK和Oracle实现带有[`Clock`]的新实现(https://docs.oracle.com/javase/9​​/docs/api/java/time/Clock.html),用于捕获分辨率小于毫秒的当前时刻.在MacBook Pro Retina上,我得到的是当前时间,以微秒为单位(小数部分的六位数).实际结果和准确性取决于主机的基础时钟硬件. (4认同)
  • 有人会猜测Java没有getTimeInMicroseconds()的原因包括1)在许多平台上不可用的准确度,2)在微秒调用中返回毫秒精度会导致应用程序可移植性问题. (3认同)

Bas*_*que 69

TL;博士

Java 9及更高版本:捕获当前时刻时的分辨率高达纳秒.这是小数部分的9位数.

Instant.now()   
Run Code Online (Sandbox Code Playgroud)

2017-12-23T12:34:56.123456789Z

要限制为微秒,请截断.

Instant                // Represent a moment in UTC. 
.now()                 // Capture the current moment. Returns a `Instant` object. 
.truncatedTo(          // Lop off the finer part of this moment. 
    ChronoUnit.MICROS  // Granularity to which we are truncating. 
)                      // Returns another `Instant` object rather than changing the original, per the immutable objects pattern. 
Run Code Online (Sandbox Code Playgroud)

2017-12-23T12:34:56.123456Z

细节

从Java 8开始,其他答案有点过时了.

java.time

Java 8及更高版本附带了java.time框架.这些新类取代了最早版本的Java附带的有缺陷的麻烦的日期时间类,例如java.util.Date/.Calendar和java.text.SimpleDateFormat.该框架由JSR 310定义,受Joda-Time的启发,由ThreeTen-Extra项目扩展.

java.time中的类解析为纳秒,比旧的日期时间类和Joda-Time使用的毫秒更精细.并且比问题中提到的微秒更精细.

在此输入图像描述

Clock 履行

虽然java.time类支持表示以纳秒为单位的值的数据,但这些类尚未生成以纳秒为单位的值.这些now()方法使用与旧日期时间类相同的旧时钟实现System.currentTimeMillis().我们Clock在java.time中有新接口,但该接口的实现与旧的毫秒时钟相同.

因此,您可以格式化结果的文本表示,ZonedDateTime.now( ZoneId.of( "America/Montreal" ) )以查看小数秒的九位数,但只有前三位数字将具有如下数字:

2017-12-23T12:34:56.789000000Z

Java 9中的新时钟

Java 9的OpenJDK和Oracle实现具有更新的默认Clock实现,具有更精细的粒度,最高可达java.time类的完整纳秒级功能.

请参阅OpenJDK问题,提高java.time.Clock.systemUTC()的实现精度.该问题已成功实施.

2017-12-23T12:34:56.123456789Z

在使用macOS Sierra的MacBook Pro(Retina,15英寸,2013年末)上,我得到当前时刻,以微秒为单位(最多六位小数).

2017-12-23T12:34:56.123456Z

硬件时钟

请记住,即使使用更精细的Clock实施,您的结果也可能因计算机而异.Java依赖于底层计算机硬件的时钟来了解当前时刻.

  • 硬件时钟的分辨率差异很大.例如,如果特定计算机的硬件时钟仅支持微秒粒度,则任何生成的日期时间值将只有六位小数秒,后三位数为零.
  • 硬件时钟的准确性差异很大.仅仅因为时钟生成一个具有几位十进制小数位的值,这些数字可能是不准确的,只是近似值,可以从原子钟读取的实际时间漂移.换句话说,仅仅因为你看到小数点右边的一串数字并不意味着你可以相信这些读数之间经过的时间对于那个分钟度是真实的.


cle*_*tus 54

你可以使用System.nanoTime():

long start = System.nanoTime();
// do stuff
long end = System.nanoTime();
long microseconds = (end - start) / 1000;
Run Code Online (Sandbox Code Playgroud)

以纳秒为单位获得时间,但这是一个严格的相对衡量标准.它没有绝对的意义.它仅用于与其他纳米时间进行比较,以衡量某些事情需要多长时间.


Jas*_*ith 14

正如其他海报已经表明的那样; 您的系统时钟可能不会同步到微秒到实际世界时间.尽管如此,微秒精度时间戳可用作指示当前壁时间和测量/分析事物持续时间的混合.

我使用诸如"2012-10-21 19:13:45.267128"之类的时间戳标记写入日志文件的所有事件/消息.这些都它发生时("墙"时间)传达,并且还可以用于测量日志文件中该事件与下一事件之间的持续时间(以微秒为单位的相对差异).

要实现这一点,您需要将System.currentTimeMillis()与System.nanoTime()链接起来,并从此刻开始专门使用System.nanoTime().示例代码:

/**
 * Class to generate timestamps with microsecond precision
 * For example: MicroTimestamp.INSTANCE.get() = "2012-10-21 19:13:45.267128"
 */ 
public enum MicroTimestamp 
{  INSTANCE ;

   private long              startDate ;
   private long              startNanoseconds ;
   private SimpleDateFormat  dateFormat ;

   private MicroTimestamp()
   {  this.startDate = System.currentTimeMillis() ;
      this.startNanoseconds = System.nanoTime() ;
      this.dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS") ;
   }

   public String get()
   {  long microSeconds = (System.nanoTime() - this.startNanoseconds) / 1000 ;
      long date = this.startDate + (microSeconds/1000) ;
      return this.dateFormat.format(date) + String.format("%03d", microSeconds % 1000) ;
   }
}
Run Code Online (Sandbox Code Playgroud)

  • 这个想法很好,但你必须时不时地重新同步.系统时间(currentTime)和CPU时钟(nanoTime)不同步,因为它们通常基于不同的硬件时钟.此外,操作系统的时间服务器会将系统时钟与外部时间源(如果可用)重新同步.因此,你看似非常精确的课程将产生时间戳,可能会有所作为! (4认同)
  • 该代码似乎不是线程安全的.两次同时调用"MicroTimestamp.INSTANCE.get()"可能会有问题. (3认同)

kan*_*gcz 6

您可以创建一个组件来确定 System.nanoTime() 和 System.currentTimeMillis() 之间的偏移量,并有效地获得自纪元以来的纳秒。

public class TimerImpl implements Timer {

    private final long offset;

    private static long calculateOffset() {
        final long nano = System.nanoTime();
        final long nanoFromMilli = System.currentTimeMillis() * 1_000_000;
        return nanoFromMilli - nano;
    }

    public TimerImpl() {
        final int count = 500;
        BigDecimal offsetSum = BigDecimal.ZERO;
        for (int i = 0; i < count; i++) {
            offsetSum = offsetSum.add(BigDecimal.valueOf(calculateOffset()));
        }
        offset = (offsetSum.divide(BigDecimal.valueOf(count))).longValue();
    }

    public long nowNano() {
        return offset + System.nanoTime();
    }

    public long nowMicro() {
        return (offset + System.nanoTime()) / 1000;
    }

    public long nowMilli() {
        return System.currentTimeMillis();
    }
}
Run Code Online (Sandbox Code Playgroud)

以下测试在我的机器上产生了相当好的结果。

    final Timer timer = new TimerImpl();
    while (true) {
        System.out.println(timer.nowNano());
        System.out.println(timer.nowMilli());
    }
Run Code Online (Sandbox Code Playgroud)

差异似乎在 +-3ms 的范围内振荡。我想可以稍微调整偏移计算。

1495065607202174413
1495065607203
1495065607202177574
1495065607203
...
1495065607372205730
1495065607370
1495065607372208890
1495065607370
...
Run Code Online (Sandbox Code Playgroud)