0

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.

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
gajesh
  • 5
  • 2
  • 2
    Why are you using generics for the method parameter but then checking for each possible class inside the method? Seems like an anti pattern. – aled Aug 31 '23 at 16:54
  • Welcome to Stack Overflow. What are you wanting your method to do in each of the cases? *coz we should able to get `instant` from `LocalDateTime` object* No, you should not. That’s like asking to have bananas from pears. Or euros from dollars when no one knows the exchange rate. Which is the reason for your error. But we would also like to tell you what to do instead, which we can’t as long as we don’t know what you want to happen. – Ole V.V. Aug 31 '23 at 21:58
  • You also won’t be able to obtain an `Instant` from a `LocalDate` or `LocalTime`. So there doesn’t seem to be any case where your method can do any real work as it currently stands. You may want to check your understanding of those classes and how they are related once more? – Ole V.V. Aug 31 '23 at 22:20
  • Thanks for the **correct comment** on my question. I am using generics here instead of Temporal directly b'coz _I do not want typecasting_ for returning value. Using this generics method, **I'll get the result in a type similar to the input type**. – gajesh Sep 01 '23 at 11:32

2 Answers2

1

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.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
1

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;
}
gajesh
  • 5
  • 2
marcinj
  • 48,511
  • 9
  • 79
  • 100