1

I have an API for JSON parsing which requires a DateTimeFormatter instance in order to parse date time strings to OffsetDateTime. However I always get an exception Unable to obtain ZoneOffset from TemporalAccessor: {},ISO resolved to 2021-08-17T13:26:49 of type java.time.format.Parsed The API uses OffsetDateTime.parse(String, DateFormatter).

// DateTimeFormatter instance to be provided to the API
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
// this is how the API uses the DateTimeFormatter instance
OffsetDateTime dateTime = OffsetDateTime.parse("20210817132649", formatter);

How do I have to create the DateTimeFormatter in order to deliver a ZoneOffset, so that the API is able to parse the DateTime correctly. The ZoneOffset may be UTC.

1
  • Yes, I tried: Unable to obtain OffsetDateTime from TemporalAccessor: {InstantSeconds=1629206809},ISO,Z resolved to 2021-08-17T13:26:49 Commented Oct 18, 2021 at 14:44

3 Answers 3

4

Update

I understood from you that you are using the API as follows:

apiClient.getJSON().setOffsetDateTimeFormat(DateTimeFormatter); 

and you do not have a parameter to pass timezone information. In this case, you can use DateTimeFormatter#withZone as shown below:

import java.time.OffsetDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.Locale;

public class Main {
    public static void main(String[] args) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("uuuuMMddHHmmss", Locale.ENGLISH)
                                        .withZone(ZoneOffset.UTC);

        OffsetDateTime odt = OffsetDateTime.parse("20210817132649", formatter);

        System.out.println(odt);
    }
}

Output:

2021-08-17T13:26:49Z

ONLINE DEMO

i.e. now, your call will be:

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("uuuuMMddHHmmss", Locale.ENGLISH)
                                .withZone(ZoneOffset.UTC);

apiClient.getJSON().setOffsetDateTimeFormat(formatter); 

Original answer

Your date-time string does not have a timezone offset. Parse it into a LocalDateTime and then apply the offset to it.

Demo:

import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.Locale;

public class Main {
    public static void main(String[] args) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("uuuuMMddHHmmss", Locale.ENGLISH);
        
        OffsetDateTime odt = LocalDateTime.parse("20210817132649", formatter)
                                .atOffset(ZoneOffset.UTC);
        
        System.out.println(odt);
    }
}

Output:

2021-08-17T13:26:49Z

ONLINE DEMO

The Z in the output is the timezone designator for zero-timezone offset. It stands for Zulu and specifies the Etc/UTC timezone (which has the timezone offset of +00:00 hours). You can specify a different timezone offset (e.g. ZoneOffset.of("+05:30")) as per your requirement.

In case you have ZoneId available

If you have ZoneId available, you should parse the given date-time string into a LocalDateTime and then apply the ZoneId to it to get a ZonedDateTime from which you can always obtain an OffsetDateTime. The best thing about a ZonedDateTime is that it has been designed to adjust the timezone offset automatically whereas an OffsetDateTime is used to represent a fixed timezone offset.

Demo:

import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;

public class Main {
    public static void main(String[] args) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("uuuuMMddHHmmss", Locale.ENGLISH);

        ZonedDateTime zdt = LocalDateTime.parse("20210817132649", formatter)
                                .atZone(ZoneId.of("Etc/UTC"));

        OffsetDateTime odt = zdt.toOffsetDateTime();

        System.out.println(odt);
    }
}

Output:

2021-08-17T13:26:49Z

ONLINE DEMO

You can specify a different ZoneId(e.g. ZoneId.of("Asia/Kolkata")) as per your requirement.

Learn more about the modern Date-Time API* from Trail: Date Time.


* If you are working for an Android project and your Android API level is still not compliant with Java-8, check Java 8+ APIs available through desugaring. Note that Android 8.0 Oreo already provides support for java.time.

Sign up to request clarification or add additional context in comments.

6 Comments

I know that the date-time string has no time-zone. But I can only provide a DateTimeFormatter to the API. Thus, I am not able to do the .atOffset(ZoneOffset.UTC).
@Stefan - Is it a Spring application?
No, I use a ApiClient generated via swagger, and can pass the DateFormatter this way: apiClient.getJSON().setOffsetDateTimeFormat(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
@Stefan - Please check if there is a way to pass the timezone e.g. timezone="UTC"
There is no property for timezone, offset or zoneId.
|
2

Well, the string you passed in does not contain zone information, while an OffsetDateTime requires zone information.

So you'll have to set a value for it.

You could use the DateTimeFormatterBuilder class, which then can be instructed to use some default value if a field is missing from the parsed information:

DateTimeFormatter formatter = new DateTimeFormatterBuilder()
    .parseDefaulting(ChronoField.OFFSET_SECONDS, 0)
    .appendPattern("yyyyMMddHHmmss")
    .toFormatter(Locale.ROOT);

You could also directly set an implied zone to the DateTimeFormatter:

DateTimeFormatter.ofPattern("yyyyMMddHHmmss").withZone(ZoneOffset.UTC);

1 Comment

The DateTimeFormatter.ofPattern("yyyyMMddHHmmss").withZone(ZoneOffset.UTC); doesn't work. However with the DateTimeFormatterBuilder is was able to get the String parsed correctly
1

Better use a ZonedDateTime - the difference being the Day Saving Time, and countries on with the same zone offset. Maybe using the default ZoneId.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.