Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

LocalDateTime as total nanoseconds

I'm working with LocalDateTime objects and would like to store these as Long with nano second precision.

I've tried converting between Instant representation but so far failing.

For example:

localDateTime.toInstant(ZoneOffset.UTC).getNano

Returns only the nano seconds segment of localDateTime - is there a way to return the complete value in nanoseconds?

Similar to toEpochSecond but rather than in seconds, nanoseconds?

like image 842
timothyclifford Avatar asked Jan 29 '23 22:01

timothyclifford


2 Answers

2262-04-11T23:47:16.854775807Z = Long.MAX_VALUE of nanos

Building on the correct Answers by Jean-Baptiste Yunès and by assylias explaining that a 64-bit long integer cannot represent all Instant values as a count of nanoseconds since 1970-01-01T00:00Z…

You could use a long/Long for a count of nanoseconds to represent moments for the next two centuries, up to 2262-04-11T23:47:16.854775807Z, if my math is correct:

Instant.ofEpochSecond( ( Long.MAX_VALUE / 1_000_000_000L ) , ( Long.MAX_VALUE % 1_000_000_000L ) )

FYI, Long.MAX_VALUE = 9223372036854775807.

I'm not saying it is a good idea to do so. I am simply showing the possibility to demonstrate the issues at hand.

See code run live at IdeOne.com.

long seconds = ( Long.MAX_VALUE / 1_000_000_000L ) ;
long fraction = ( Long.MAX_VALUE % 1_000_000_000L ) ;
long total = ( ( seconds * 1_000_000_000L ) + fraction ) ; 
Instant instant = Instant.ofEpochSecond( seconds , fraction ) ;

System.out.println( "Long.MAX_VALUE: " + Long.MAX_VALUE ) ;
System.out.println( "seconds: " + seconds ) ;
System.out.println( "fraction: " + fraction ) ;
System.out.println( "total: " + total ) ;
System.out.println( "instant: " + instant ) ;

Long.MAX_VALUE: 9223372036854775807

seconds: 9223372036

fraction: 854775807

total: 9223372036854775807

instant: 2262-04-11T23:47:16.854775807Z

like image 193
Basil Bourque Avatar answered Jan 31 '23 13:01

Basil Bourque


There is no such method because you can't store all instants in a long number of nanoseconds.

If you are happy that the range of dates you are interested in can all fit in a long as a number of nanoseconds since the epoch, you can calculate it yourself with:

long nanos = ( instant.getEpochSecond * 1_000_000_000L ) + instant.getNano

Note that this will overflow if the date is too far in the past or the future.

like image 34
assylias Avatar answered Jan 31 '23 12:01

assylias