1

String is in this format - "2021-07-13 05:22:18.712"

I tried using this code to parse it. OffsetDateTime parsedDateTime = OffsetDateTime.parse("2021-07-13 05:22:18.712");

But i keep getting this error - org.threeten.bp.format.DateTimeParseException: Text '2021-07-13 05:22:18.712' could not be parsed at index 10.

How do i make it work? Any suggestions will be helpful. Thanks

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
Vaibhav
  • 47
  • 5
  • 1
    "2021-07-13 05:22:18.712" does not have an offset in it. What offset do you want your `parsedDateTime` to have? – Sweeper Jul 13 '21 at 06:03
  • What did your search turn up? Was [the tutorial](https://docs.oracle.com/javase/tutorial/datetime/index.html) helpful? – Ole V.V. Jul 13 '21 at 06:43

2 Answers2

3

You need to decide on a time zone (or at least on an offset, but time zone is usually the correct means). And then you need to use a formatter that defines the format that you are trying to parse:

private static final DateTimeFormatter FORMATTER = new DateTimeFormatterBuilder()
        .append(DateTimeFormatter.ISO_LOCAL_DATE)
        .appendLiteral(' ')
        .append(DateTimeFormatter.ISO_LOCAL_TIME)
        .toFormatter(Locale.ROOT);

With this formatter it’s a pretty simple operation:

    ZoneId zone = ZoneId.of("Asia/Kolkata");
    String input = "2021-07-13 05:22:18.712";
    
    OffsetDateTime dateTime = LocalDateTime.parse(input, FORMATTER)
            .atZone(zone)
            .toOffsetDateTime();
    
    System.out.println(dateTime);

Output from the example snippet is:

2021-07-13T05:22:18.712+05:30

Since as @Sweeper noted in a comment your string does not contain UTC offset nor time zone, parse it into a LocalDateTime first. The Local in some java.time class names means without time zone or UTC offset. Then convert into a ZonedDateTime in the intended time zone and further into the desired type, OffsetDateTime.

If you want to use the default time zone of the JVM, set zone to ZoneId.systemDefault(). Be aware that the default time zone may be changed at any time from another part of your program or another program running in the same JVM, so this is fragile.

Possible shortcuts

My formatter is wordy because I wanted to reuse as much as I could from built-in formatters. If you don’t mind building the formatter by hand from a pattern, you may use:

private static final DateTimeFormatter FORMATTER
        = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss.SSS", Locale.ROOT);

Or even shorter, you may hand substitute the space in your string with a T to obtain ISO 8601 format and then parse into a LocalDateTime without specifying any formatter at all.

What went wrong in your code?

The exception message you got is trying to be helpful:

But i keep getting this error - org.threeten.bp.format.DateTimeParseException: Text '2021-07-13 05:22:18.712' could not be parsed at index 10.

Index 10 in your string is where the space between date and time is. The one-arg OffsetDateTime.parse method expects ISO 8601 format, like 2021-07-13T05:22:18.712+05:30, so with a T to denote the start of the time part and with a UTC offset at the end. The absence of the T caused your exception. Had you fixed that, you would have got another exception because of the missing UTC offset.

Wikipedia article: ISO 8601

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
  • Thank you so much @ole V.V , this helped a lott. was not expecting this much detail. can't thank you enough. – Vaibhav Jul 14 '21 at 05:12
2

You first need to check the document.

It indicates parse need to go with a date format such as 2007-12-03T10:15:30 +01:00.

You date is missing a "T", "2021-07-13 05:22:18.712". Hence it did not go well, counting it from index 0, it's character at 10.

If you need to parse 2021-07-13T05:22:18.712, you will still get error. An error Text '2021-07-13T05:22:18.712' could not be parsed at index 23. Which is the problem of miliseconds.

So a big round to go:

//Format to date
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); 
//Format to new string
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssX"); 
java.util.Date date1=simpleDateFormat.parse("2021-07-13 05:22:18.712");
String newDate = formatter.format(date1);

//finally.    
OffsetDateTime parsedDateTime = OffsetDateTime.parse(newDate);
Han
  • 728
  • 5
  • 17
  • Very strongly discouraged. Please don’t teach the young ones to use the long outdated and notoriously troublesome `SimpleDateFormat` class. At least not as the first option. And not without any reservation. We have so much better in [`java.time`, the modern Java date and time API,](https://docs.oracle.com/javase/tutorial/datetime/) and its `DateTimeFormatter`. And OPI is already using java.time. – Ole V.V. Jul 13 '21 at 11:25
  • BTW it’s also not correct. I tried with the string `2021-07-13 12:27:38.667` and expected `2021-07-13T12:27:38.667+02:00` in my time zone. Instead I got `2021-07-13T00:27:38+02:00`. It’s 12 hours 667 milliseconds off. – Ole V.V. Jul 13 '21 at 11:29
  • But the explanation of what was wrong or missing is good and almost correct. :-) – Ole V.V. Jul 13 '21 at 11:34
  • Ole V. V., yeah forgotten it's 24H. fixed. – Han Jul 13 '21 at 23:52
  • 1
    But i agree your answer is much more precise and right, yours should be an accepted answer. It's also non Thread safe with this method of SimpleDateFormat I'm using. I got left out using java.time, but it's great that i'm learning this too. Thanks for the info. – Han Jul 13 '21 at 23:54