在 java 语言中,如何将纳秒值,例如 1568694302232954486 和 1568703521360049938 转换为 Java 日期对象?

In java language, how to convert nano seconds value, for example 1568694302232954486 and 1568703521360049938 into a Java Date object?

我有很多看起来像 1568694302232954486 和 1568703521360049938 的长数字,我需要将它们中的每一个都转换成一个 Java 日期对象。

如何在Java8中实现上述需求? 我还需要将纳秒值转换为 elasticsearch 的时间戳,并找到了正确的方法;感谢大家的帮助!

以下代码块已通过测试,仅供需要者参考。它实际上是 logstash 配置文件的一部分:

ruby {
            init => ""
            code => "
            event.set('time_local',event.get('time_local').to_f*0.000001)
            "
        }

        date {
                #15/Aug/2019:14:46:19 +0800 [02/Sep/2019:09:28:33 +0800]
            match => [ "time_local" , "yyyy-MM-dd HH:mm:ss,SSS","UNIX_MS"]
            timezone => "Asia/Shanghai"
            target => "@timestamp"
        }

如果你想要它作为一个 Date 对象,那么你将丢失一些信息,因为 Date 只有毫秒精度。 Date 在 Java 8 中也已过时,因此如果您使用 Java 8 或更高版本,请考虑改用 Instant

这是转换为 Date 的方法。不要这样做,除非你真的必须这样做。

long nano = 1568694302232954486L;
Date d = new Date(nano / 1000000); // 1000000 is how many nanoseconds there are in a millisecond
另一方面,

Instant 具有纳秒精度,这是您应该做的:

// 1000000000 is how many nanoseconds there are in a second.
Instant i = Instant.ofEpochSecond(nano / 1000000000, nano % 1000000000);

java.time

知道怎么做就很容易了。虽然双参数 Instant.ofEpochSecond() 的第二个参数名为 nanoAdjustment,但它的类型为 long,并且该方法接受在此参数中传递的完整 nano 值。所以只需将 0 作为秒传递,并将转换留给方法:

    Instant instant1 = Instant.ofEpochSecond(0, 1_568_694_302_232_954_486L);
    System.out.println(instant1);
    Instant instant2 = Instant.ofEpochSecond(0, 1_568_703_521_360_049_938L);
    System.out.println(instant2);

输出为:

2019-09-17T04:25:02.232954486Z
2019-09-17T06:58:41.360049938Z

如果您确实需要一个老式的 Date 旧对象 API,您现在无法更改或不想升级:

    Date oldfashionedDate1 = Date.from(instant1);
    System.out.println(oldfashionedDate1);

在我的电脑上,转换后的 Date 打印为:

Tue Sep 17 06:25:02 CEST 2019

不过,通常要避免 Date class。它设计不佳且早已过时。使用 java.time,现代 Java 日期和时间 API,要好得多。

Link: Oracle tutorial: Date Time 解释如何使用 java.time.