Как получить наносекунды с эпохи для строкового формата времени "2019-01-25 14: 34: 34.123456789" в Java? - PullRequest
0 голосов
/ 10 мая 2019

Я могу разобрать 2019-01-25 14:34:34.123456789 строку и получить объект ZonedDateTime.Теперь я хочу получить время с точностью до наносекунды с момента создания этого ZonedDateTime объекта.

Ответы [ 2 ]

1 голос
/ 10 мая 2019

Продолжительность может помочь:

Что-то вроде:

Duration.between(
  ZonedDateTime.ofInstant(Instant.EPOCH, ZoneId.of("UTC")),
  yourZonedDatetime
).toNanos()
0 голосов
/ 13 мая 2019

Это будет работать до 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()));

Результат тот же.

Плюсы и минусы: в моем коде немного больше ручной работы, чем в коде Славомира Ходницкого, что, безусловно, является недостатком.С другой стороны, я не нашел здесь использование Duration очень хорошо мотивированным, и это не сработает и после 2262 года (бросает ArithmeticException).Идеального решения не существует.

...