converting epoch to ZonedDateTime in Java

2019-08-12 05:03发布

问题:

How to convert epoch like 1413225446.92000 to ZonedDateTime in java?

The code given expects long value hence this will throw NumberFormatException for the value given above.

ZonedDateTime.ofInstant(Instant.ofEpochMilli(Long.parseLong(dateInMillis)), ZoneId.of(TIME_ZONE_PST));

回答1:

Basil Bourque’s answer is a good one. Taking out the nanoseconds from the fractional part into an integer for nanoseconds may entail a pitfall or two. I suggest:

    String dateInMillis = "1413225446.92000";
    String[] secondsAndFraction = dateInMillis.split("\\.");
    int nanos = 0;
    if (secondsAndFraction.length > 1) { // there’s a fractional part
        // extend fractional part to 9 digits to obtain nanoseconds
        String nanosecondsString
                = (secondsAndFraction[1] + "000000000").substring(0, 9);
        nanos = Integer.parseInt(nanosecondsString);
        // if the double number was negative, the nanos must be too
        if (dateInMillis.startsWith("-")) {
            nanos = -nanos;
        } 
    }
    ZonedDateTime zdt = Instant
            .ofEpochSecond(Long.parseLong(secondsAndFraction[0]), nanos)
            .atZone(ZoneId.of("Asia/Manila"));
    System.out.println(zdt);

This prints

2014-10-14T02:37:26.920+08:00[Asia/Manila]

We don’t need 64 bits for the nanoseconds, so I am just using an int.

If one day your epoch time comes in scientific notation (1.41322544692E9), the above will not work.

Please substitute your desired time zone in the region/city format if it didn’t happen to be Asia/Manila, for example America/Vancouver, America/Los_Angeles or Pacific/Pitcairn. Avoid three letter abbreviations like PST, they are ambiguous and often not true time zones.



回答2:

Split the number into a pair of 64-bit long integers:

  • Number of whole seconds since the epoch reference date of first moment of 1970 in UTC
  • A number of nanoseconds for the fractional second

Pass those numbers to the factory method Instant.ofEpochSecond​(long epochSecond, long nanoAdjustment)

With an Instant in hand, proceed to assign a time zone to get a ZonedDateTime.

ZoneId z = ZoneId.of( "America/Los_Angeles" ) ;
ZonedDateTime zdt = instant.atZone( z ) ;