20

I am trying to convert a string in OffsetDateTime but getting below error.

java.time.format.DateTimeParseException: Text '20150101' could not be parsed: Unable to obtain OffsetDateTime from TemporalAccessor: {},ISO resolved to 2015-01-01 of type java.time.format.Parsed

Code : OffsetDateTime.parse("20150101", DateTimeFormatter.ofPattern("yyyyMMdd"));

Expected output: OffsetDateTime object with date 20150101.

I really appreciate any help you can provide.

Thanks,

harshavmb
  • 3,404
  • 3
  • 21
  • 55

5 Answers5

14

OffsetDateTime represents a date-time with an offset , for eg.

2007-12-03T10:15:30+01:00

The text you are trying to parse does not conform to the requirements of OffsetDateTime. See https://docs.oracle.com/javase/8/docs/api/java/time/OffsetDateTime.html

The string being parsed neither contains the ZoneOffset nor time. From the string and the pattern of the formatter, it looks like you just need a LocalDate. So, you could use :

LocalDate.parse("20150101", DateTimeFormatter.ofPattern("yyyyMMdd"));
Pallavi Sonal
  • 3,661
  • 1
  • 15
  • 19
5

Thanks everyone for your reply. Earlier I was using joda datetime (look at below method) to handle date and datetime both but I wanted to use Java8 libraries instead of the external libraries.

static public DateTime convertStringInDateFormat(String date, String dateFormat){
    DateTimeFormatter formatter = DateTimeFormat.forPattern(dateFormat);
return formatter.parseDateTime(date);
}

I was expecting same with OffsetDateTime but got to know we can use ZonedDateTime or OffsetDateTime if we want to work with a date/time in a certain time zone. As I am working on Period and Duration for which LocalDate can help.

String to DateTime:

LocalDate date =
LocalDate.parse("20150101", DateTimeFormatter.ofPattern("yyyyMMdd"));

LocalDate to desired string format:

String dateFormat = "yyyy-MM-dd'T'HH:mm:ss'Z'";
date.atStartOfDay().format(DateTimeFormatter.ofPattern(dateFormat));
  • 2
    Correct understanding. Tip: on that last line, I recommend **always passing an explicit `ZoneId` to that `atStartOfDay`** call. Example: `.atStartOfDay( ZoneId.of( " Africa/Lagos" ) )` Otherwise you are implicitly getting the JVM’s current default time zone. Better to be explicit about your desired/expected time zone. And, that default can be changed at any moment *during* runtime by any code in the JVM, so the default is unreliable. For example, given what you said in you Question, you would be getting the start of a Chicago day rather than the start of a Lagos day. – Basil Bourque Jun 04 '17 at 16:28
  • Another note, `LocalDate` is for `Period` as that class represents a span of time with a granularity of years, months, days. But a `Duration` is a span of time as a total number of seconds plus a fraction of a second in nanoseconds. So a `Duration` applies to date-time values such as `Instant`, `OffsetDateTime`, and `ZonedDateTime` rather than a date-only `LocalDate`. – Basil Bourque Jun 04 '17 at 16:35
2

As Pallavi said correctly OffsetDateTime makes only in the context of a offset. Hence to go from a date string to an OffsetDateTime, you need a timezone!

Here is the recipe. Find yourself a Timezone, UTC or other.

ZoneId zoneId = ZoneId.of("UTC");   // Or another geographic: Europe/Paris
ZoneId defaultZone = ZoneId.systemDefault();

Make the LocalDateTime, works the same with LocalDate.

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS");    
LocalDateTime dateTime = LocalDateTime.parse("2022-01-28T14:29:10.212", formatter);

An offset makes only sense for a timezone and a time. For instance, Eastern Time hovers between GMT-4 and GMT-5 depending on the time of year.

ZoneOffset offset = zoneId.getRules().getOffset(dateTime);

Finally you can make your OffsetDateTime from both the time and the offset:

OffsetDateTime offsetDateTime = OffsetDateTime.of(dateTime, offset);

Hope this helps anyone.

Patrice Gagnon
  • 1,276
  • 14
  • 14
1

Use a LocalDate instead of offsetDatetime for your case as you want to parse only date (no time/offset). The usage of offsetDatetime is very well discussed here

Uday
  • 1,165
  • 9
  • 12
  • 2
    You may then use for example `atStartOfDay().atOffset(yourDesiredOffset)` to convert into an `OffsetDateTime`. Offset could be for instance `ZoneOffset.UTC`. It’s a good thing that the date and time classes often force you to be specific about what you want instead of giving you default values that may not match your needs. – Ole V.V. Jun 01 '17 at 11:34
1

Z not literal

The accepted answer has a serious problem: it uses the literal, 'Z' in the pattern to specify the UTC offset. 'Z' is just a character literal whereas Z is the timezone designator for zero-timezone offset. It stands for Zulu and specifies the UTC offset (+00:00 hours). Check 'Z' is not the same as Z to learn more about it.

DateTimeFormatter.ofPattern( "yyyy-MM-dd'T'HH:mm:ssZ" )  // Z is a formatting code, not a string literal.

DateTimeFormatter.BASIC_ISO_DATE

Apart from this, the parsing code can be improved by using the predefined formatted, DateTimeFormatter#BASIC_ISO_DATE.

LocalDate.parse("20150101", DateTimeFormatter.BASIC_ISO_DATE)

Specify time zone

Also, one should always specify a timezone explicitly; otherwise, the JVM will use the system's default timezone, a common cause of many problems developers face.

Demo:

class Main {
    public static void main(String[] args) {
        LocalDate date = LocalDate.parse("20150101", DateTimeFormatter.BASIC_ISO_DATE);

        // Convert date into a ZonedDateTime at the start of the day in the 
        // desired timezone e.g. ZoneId.of("Etc/UTC")
        ZonedDateTime zdt = date.atStartOfDay(ZoneId.of("Etc/UTC"));

        // Convert the obtained ZonedDateTime into an OffsetDateTime
        OffsetDateTime odt = zdt.toOffsetDateTime();
        System.out.println(odt);
    }
}

Output:

2015-01-01T00:00Z

Online Demo

Learn about the modern date-time API from Trail: Date Time

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
Arvind Kumar Avinash
  • 71,965
  • 6
  • 74
  • 110
  • Perhaps better to use `ZoneOffset.UTC` constant rather than `ZoneId.of("Etc/UTC")`. Or choose some arbitrary time zone as an example. – Basil Bourque Sep 02 '23 at 20:44
  • Thanks, @BasilBourque for the valuable edits and the recommendation to use `ZoneOffset.UTC`. I wrote the code in my IDE using `ZoneOffset.UTC` but changed it to `ZoneId.of("Etc/UTC")` before posting my answer. The reason I did so because many developers do not realise that [`ZoneOffset` extends `ZoneId`](https://docs.oracle.com/javase/8/docs/api/java/time/ZoneOffset.html) and get confused with `ZoneId` in [`LocalDate#atStartOfDay(ZoneId)`](https://docs.oracle.com/javase/8/docs/api/java/time/LocalDate.html#atStartOfDay-java.time.ZoneId-). – Arvind Kumar Avinash Sep 02 '23 at 21:29