如何在 java 中获取字符串格式时间“2019-01-25 14:34:34.123456789”自纪元以来的纳秒数?

How to get nanoseconds since epoch for string formatted time "2019-01-25 14:34:34.123456789" in java?

我能够解析 2019-01-25 14:34:34.123456789 字符串并获取 ZonedDateTime 的对象。 现在,我想从这个 ZonedDateTime 对象中获取自纪元以来的纳秒精度级别的时间。

Duration 可能有帮助:

类似于:

Duration.between(
  ZonedDateTime.ofInstant(Instant.EPOCH, ZoneId.of("UTC")),
  yourZonedDatetime
).toNanos()

这将一直有效到 2262 年:

    ZonedDateTime zdt = LocalDateTime.of(2019, 1, 25, 14, 34, 34, 123456789)
            .atZone(ZoneId.of("Asia/Kolkata"));
    Instant i = zdt.toInstant();
    long epochNano = Math.addExact(Math.multiplyExact(i.getEpochSecond(), TimeUnit.SECONDS.toNanos(1)),
            i.getNano());
    System.out.println(NumberFormat.getNumberInstance(Locale.ENGLISH).format(epochNano));

输出:

1,548,407,074,123,456,789

为什么我不只是使用 TimeUnit.SECONDS.toNanos(i.getEpochSecond()) 是因为在溢出的情况下这只会给我 Long.MAX_VALUE,即不正确的结果。 Math.multiplyExact 会在溢出时抛出异常,所以我们会发现,我显然更喜欢。

为避免在 2262 年及以后出现溢出,请使用 BigInteger:

    BigInteger epochNano = BigInteger.valueOf(i.getEpochSecond())
            .multiply(BigInteger.valueOf(TimeUnit.SECONDS.toNanos(1)))
            .add(BigInteger.valueOf(i.getNano()));

结果是一样的

优点和缺点:我的代码比 Slawomir Chodnicki 的代码多了一点手工,这当然是一个缺点。另一方面,我也没有发现这里使用 Duration 的动机非常好,而且在 2262 年之后也不会起作用(抛出 ArithmeticException)。完美的解决方案并不存在。