3

I am trying to convert string to Date object in Java 11. the below code giving me the exception. tried different method, so far no luck. Any help to resolve this error message?

String date = 'Mon Aug 02 16:33:10 EDT 2021'
OffsetDateTime odt = OffsetDateTime.now( ZoneId.systemDefault() ) ;
DateTimeFormatter formatter = new DateTimeFormatterBuilder().appendPattern("E MMM d H:m:s z yyyy").toFormatter().ofLocalizedDateTime(FormatStyle.LONG) .withZone(odt.getOffset());
LocalDateTime  localDateTime = LocalDateTime.parse(date, formatter);
System.out.println(localDateTime);
System.out.println(formatter.format(localDateTime));

Error

Exception in thread "main" java.time.format.DateTimeParseException: Text 'Mon Aug 02 16:33:10 EDT 2021' could not be parsed at index 20
    at java.base/java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:2046)
    at java.base/java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1948)
    at java.base/java.time.LocalDateTime.parse(LocalDateTime.java:492)
    at java_time_LocalDateTime$parse.call(Unknown Source)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:47)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:125)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:148)
Savior
  • 3,225
  • 4
  • 24
  • 48
sfgroups
  • 18,151
  • 28
  • 132
  • 204

3 Answers3

1

A good IDE would have produced a warning for the code you're attempting to compile. For example, Eclipse warns

The static method ofLocalizedDateTime(FormatStyle) from the type DateTimeFormatter should be accessed in a static way

Java allows you to access static members of a class through reference expressions. Still, there's strong consensus that you should not, and just ignore the language feature.

For your specific case,

new DateTimeFormatterBuilder().appendPattern("E MMM d H:m:s z yyyy")
            .toFormatter()
            .ofLocalizedDateTime(FormatStyle.LONG)
            .withZone(odt.getOffset());

The static DateTimeFormatter#ofLocalizedDate(FormatStyle) is invoked on the reference expression [...].toFormatter() which is of type DateTimeFormatter. You seem to think that it's invoked on the actual DateTimeFormatter instance, but it's actually just a static method invocation. The instance returned by .toFormatter() is discarded. Your code is essentially equivalent to

new DateTimeFormatterBuilder().appendPattern("E MMM d H:m:s z yyyy")
            .toFormatter(); // thrown away

DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.LONG)
            .withZone(odt.getOffset());

In other words, your formatter has a format selected by ofLocalizedDateTime, not the "E MMM d H:m:s z yyyy" you were trying to use. Presumably, for your default Locale, that format cannot parse your date string.

It's unclear whether you meant to use that method. If you know of a corresponding locale with an appropriate format, you can skip your custom pattern and just use the one selected

Locale currentLocale = /* whatever is appropriate */;
DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.LONG)
         .withLocale(currentLocale);

and then parse your date string.

Otherwise, ignore the method altogether and just build your DateTimeFormatter with the pattern and timezone you were providing:

DateTimeFormatter formatter = new DateTimeFormatterBuilder().appendPattern("E MMM d H:m:s z yyyy")
                .toFormatter()
                .withZone(odt.getOffset());

You can tell from the DateTimeFormatter class javadoc, that your pattern string

E MMM d H:m:s z yyyy

can appropriately parse your date string

Mon Aug 02 16:33:10 EDT 2021

Unrelated, are you sure LocalDateTime is what you need? You essentially lose the timezone information (EDT) from your original string. Also, the ZoneId provided to withZone will be ignored for parsing to a LocalDateTime.

Savior
  • 3,225
  • 4
  • 24
  • 48
0

Use the pattern, EEE MMM dd HH:mm:ss z yyyy.

Also, since you have timezone instead of the offset in the date-time string, you should use ZonedDateTime instead of OffsetDateTime.

import java.time.LocalDateTime;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;

public class Main {
    public static void main(String[] args) {
        String strDate = "Mon Aug 02 16:33:10 EDT 2021";
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("EEE MMM dd HH:mm:ss z yyyy");
        ZonedDateTime zdt = ZonedDateTime.parse(strDate, formatter);
        System.out.println(zdt);

        LocalDateTime ldt = zdt.toLocalDateTime();
        System.out.println(ldt);
    }
}

Output:

2021-08-02T16:33:10-04:00[America/New_York]
2021-08-02T16:33:10

Note (Courtesy Basil Bourque): It almost certainly makes no sense to convert from ZonedDateTime to LocalDateTime. That conversion throws away valuable information, the time zone, without adding any value.

Arvind Kumar Avinash
  • 71,965
  • 6
  • 74
  • 110
  • 1
    The explanation should be verbose, because you've completely ignored the root cause. The problem here is they're using the static factory method `ofLocalizedDateTime` in a non-static way, completely skipping the `DateTimeFormatterBuilder` they've been constructing along the way. There is nothing wrong with their format. – Savior Jun 22 '20 at 16:02
  • 1
    @OleV.V. [For your consideration.](https://stackoverflow.com/a/62561047/5191913) – Savior Jun 24 '20 at 17:47
0

In my case the date string I was parsing had the am/pm in lower case, like this

May 12 2021 at 3:31 pm

I had to first convert the 'pm' to 'PM' and then use formatter DateTimeFormatter.ofPattern("MMMM d yyyy 'at' h:mm a");

AJC
  • 981
  • 10
  • 17