Reputation: 60
I am able to parse 2019-01-25 14:34:34.123456789
string and get the object of ZonedDateTime
.
Now, I want to get time in nanoseconds precision level since epoch from this ZonedDateTime
object.
Upvotes: 0
Views: 186
Reputation: 1545
Duration might help:
Something like:
Duration.between(
ZonedDateTime.ofInstant(Instant.EPOCH, ZoneId.of("UTC")),
yourZonedDatetime
).toNanos()
Upvotes: 1
Reputation: 86296
This will work until year 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));
Output:
1,548,407,074,123,456,789
Why I am not just using TimeUnit.SECONDS.toNanos(i.getEpochSecond())
is in case of overflow this would just give me Long.MAX_VALUE
, that is, an incorrect result. Math.multiplyExact
will throw an exception in case of overflow, so we will discover, which I clearly prefer.
To avoid overflow in year 2262 and later use BigInteger
:
BigInteger epochNano = BigInteger.valueOf(i.getEpochSecond())
.multiply(BigInteger.valueOf(TimeUnit.SECONDS.toNanos(1)))
.add(BigInteger.valueOf(i.getNano()));
The result is the same.
Pros and cons: There’s a little more handwork in my code than in the code by Slawomir Chodnicki, which is certainly a disadvantage. On the other hand I didn’t find the use of Duration
very well motivated here either, and that will not work after year 2262 either (throws an ArithmeticException
). The perfect solution doesn’t exist.
Upvotes: 0