Unable to obtain Instant from TemporalAccessor: 2023-08-31T20:37:49.005832800 of type java.time.LocalDateTime

1k Views Asked by At

I am using parmeterised method for Temporal class and passing LocalDateTime to Temporal argument and getting error in Instant.from(Temporal t) method where, t instancof LocalDateTime in my case. Here is program,

public Class DateTimeUtils {
public static <T extends Temporal> T withZone(T datetime, ZoneId zone) {
        ZonedDateTime zdt = Instant.from(datetime).atZone(zone);    //error Unable to obtain Instant from TemporalAccessor for LocalDateTime
        if (datetime instanceof LocalDate)
            return (T) zdt.toLocalDate();
        else if (datetime instanceof LocalTime)
            return (T) zdt.toLocalTime();
        else if (datetime instanceof LocalDateTime)
            return (T) zdt.toLocalDateTime();
        else if (datetime instanceof Instant)
            return (T) zdt.toInstant();
        else
          return datetime;
}
//getting error while calling DateConvertUtils.withZone function through main
   public static void main(String[] args) {
        System.out.println(LocalDateTime.now());
        System.out.println(DateConvertUtils.withZone(LocalDateTime.now(), ZoneId.systemDefault()));
    }
}

Following error is occured while runing this file

Exception in thread "main" java.time.DateTimeException: Unable to obtain Instant from TemporalAccessor: 2023-08-31T20:37:49.005832800 of type java.time.LocalDateTime
    at java.base/java.time.Instant.from(Instant.java:378)
    at javaapplicationpjl.DateConvertUtils.withZone(DateConvertUtils.java:?)
    at javaapplicationpjl.DateConvertUtils.main(DateConvertUtils.java:?)
Caused by: java.time.temporal.UnsupportedTemporalTypeException: Unsupported field: InstantSeconds
    at java.base/java.time.LocalDate.get0(LocalDate.java:708)
    at java.base/java.time.LocalDate.getLong(LocalDate.java:687)
    at java.base/java.time.LocalDateTime.getLong(LocalDateTime.java:720)
    at java.base/java.time.Instant.from(Instant.java:373)
    ... 2 more

Request you to tell me the reason of this error b'coz we should able to get instant from LocalDateTime object and also request you to improvise my function: withZone(..). Purpose of this function is very clear. Thanks in advance.

I am trying to prepare a generic function for getting time library class object with zone specific where input and output type is both and both must be instance of Temporal.

Got **error **while I have tried it when accessing Instant.from(LocalDateTime) method.

2

There are 2 best solutions below

0
marcinj On BEST ANSWER

ZonedDateTime zdt = Instant.from(datetime).atZone(zone); //error Unable to obtain Instant from TemporalAccessor for LocalDateTime

This error is because LocalDateTime does not contain information about the offset from UTC Greenwich, which is required to convert it to an Instant. This exception is thrown in Instant.from before it reches atZone. LocalDateTime does implement TemporalAccessor, but but does not support time zone:

https://docs.oracle.com/javase/8/docs/api/java/time/LocalDateTime.html

This class does not store or represent a time-zone. Instead, it is a description of the date, as used for birthdays, combined with the local time as seen on a wall clock. It cannot represent an instant on the time-line without additional information such as an offset or time-zone.

You can convert LocalDateTime to ZonedDateTime using specified ZoneID, and then convert it to Instant:

public static <T extends Temporal> T withZone(T datetime, ZoneId zone) {
    ZonedDateTime zdt;
    if (datetime instanceof LocalDateTime) {
        zdt = ((LocalDateTime) datetime).atZone(zone);
    else if(datetime instanceof LocalDate) {
        zdt = ((LocalDate) datetime).atStartOfDay(zone);
    } else {
        zdt = Instant.from(datetime).atZone(zone);
    }
    if (datetime instanceof LocalDate)
        return (T) zdt.toLocalDate();
    else if (datetime instanceof LocalTime)
        return (T) zdt.toLocalTime();
    else if (datetime instanceof LocalDateTime)
        return (T) zdt.toLocalDateTime();
    else if (datetime instanceof Instant)
        return (T) zdt.toInstant();
    else
        return datetime;
}
0
Basil Bourque On

tl;dr

You cannot make an Instant from a LocalDateTime without injecting the context of a time zone or offset.

myLocalDateTime.atZone( … ).toInstant()

Details

error in Instant.from(Temporal t) method where, t instanceof LocalDateTime

LocalDateTime is merely a date with a time of day. That class has no concept of time zone nor offset from UTC. Objects of this class do not represent a moment, a specific point on the timeline.

Instant does represent a moment, a specific point on the timeline, as seen with an offset from UTC of zero hours-minutes-seconds.

So you cannot make an Instant from a LocalDateTime.

For example, “noon on January 23, 2024”, we cannot know if that is noon in Tokyo, Toulouse, or Toledo — three different moments several hours apart on the timeline.

If we know that was meant to be a moment in Toulouse France, we could do the following to get an Instant.

Instant instant =
    LocalDateTime
        .of( 2024 , 1 , 23 , 12 , 0 , 0 , 0 ) 
        .atZone( ZoneId.of( "Europe/Paris" ) )
        .toInstant() ;

See this code run at Ideone.com. The Z on the end means an offset of zero.

2024-01-23T11:00:00Z


By the way, I do not see the purpose of your DateTimeUtils. The more general interfaces such as Temporal are not intended for common app programming; they are for implementors of date-time classes.

If that class was an attempt at solving a particular problem, I suggest you post another Question on that topic. I suspect we can find a better approach.