Your Question in inconsistent with two different kinds of input. First we will look at the whole seconds, then we will look at the input with a decimal fraction.
Whole Seconds
No need for multiplying by a thousand when the input is a count of seconds since epoch reference date. The Instant
class offers the static method ofEpochSecond
to handle whole seconds.
OffsetDateTime
When working with only an offset-from-UTC (or UTC itself), use the OffsetDateTime
class. The ZonedDateTime
class is for assigning a full time zone. A full time zone is an offset-from-UTC plus a set of rules for handling anomalies such as Daylight Saving Time (DST).
So what is the difference between an Instant
and an OffsetDateTime
assigned UTC as the offset? No difference in the meaning, both represent the same moment. But the OffsetDateTime
has additional features. One such feature is flexible formatting when generating a String representation, whereas an Instant
is not intended for formatting other than its own toString
method.
String input = "480364794";
Instant instant = Instant.ofEpochSecond ( Long.parseLong ( input ) );
OffsetDateTime odt = OffsetDateTime.ofInstant ( instant , ZoneOffset.UTC );
System.out.println ( "input: " + input + " | instant: " + instant + " | odt: " + odt );
When run.
input: 480364794 | instant: 1985-03-22T18:39:54Z | odt: 1985-03-22T18:39:54Z
Fractional Second
For the input of a fractional second, separate the whole number of seconds from the fraction. Then pass each to a static factory method, Instant.ofEpochSecond
taking two arguments.
One way of getting those numbers is through BigDecimal
. We do not use double
/float
because those data types trade away accuracy for speed of execution.
See this Question for discussion of extracting fractional part of a BigDecimal
. Note especially this Answer and this Answer.
BigDecimal input = new BigDecimal ( "444663422.631236" );
// Seconds
long seconds = input.longValue (); // = 444,663,422. Truncates the fraction. Only the whole number portion remains.
// Nanoseconds
BigDecimal fractionalSecond = input.remainder ( BigDecimal.ONE ); // = 0.631236. Truncates whole number. Only decimal fraction remains.
int decimalPlacesForNanoseconds = 9;
if ( fractionalSecond.scale () > decimalPlacesForNanoseconds ) { // Too many decimal places?
// FIXME: Handle this error condition. This means data loss as our input has a granularity finer than nanoseconds.
System.out.println ( "ERROR - Input finer than nanoseconds. Message # 0aa71e3b-6a5b-4ac4-b239-68e6b9f12284." );
}
BigInteger nanosBI = fractionalSecond.movePointRight ( decimalPlacesForNanoseconds ).toBigInteger (); // Make a whole number from the fraction.
long nanos = nanosBI.longValue ();
// Instant = ( Seconds + Nanoseconds )
Instant instant = Instant.ofEpochSecond ( seconds , nanos );
Dump to console.
System.out.println ( "input: " + input + " | seconds: " + seconds + " | nanos: " + nanos + " | instant: " + instant );
When run.
input: 444663422.631236 | seconds: 444663422 | nanos: 631236000 | instant: 1984-02-03T13:37:02.631236Z