Search code examples
javadatedatetimedayofweekdate-parsing

Java Time parse Dates with short day names


I've got the following German date: So, 18 Jul 2021 15:24:00 +0200

I'm unable to parse it using Java Time:

DateTimeFormatter.ofPattern("EEE, dd MMM yyyy HH:mm:ss Z", Locale.GERMANY)
  .parse("So, 18 Jul 2021 15:24:00 +0200", Instant::from)

as it throws: Text 'So, 18 Jul 2021 15:24:00 +0200' could not be parsed at index 0

If I were to change the string to be properly formatted it works:

-So, 18 Jul 2021 15:24:00 +0200
+So., 18 Juli 2021 15:24:00 +0200

Is there any magic pattern to parse the above date?


I've also got the same problem for other dates

  • LocalDateTime.parse("ven, 16/07/2021 - 09:49", DateTimeFormatter.ofPattern("EE, dd/MM/yyyy - HH:mm", Locale("fr")))
    • ven must be ven.
  • LocalDateTime.parse("vr, 23 apr 2021 17:04:00", DateTimeFormatter.ofPattern("EE, dd MM yyyy HH:mm:ss", Locale("nl")))
    • apr must be 04 (in order to use MM)

Solution

  • The modern Date-Time API is very particular about the pattern. So, it is almost impossible to create a single pattern that you can use to parse all types of strings. However, one of the greatest features of DateTimeFormatter is its flexibility to work with optional patterns, specified using the square bracket e.g. the following demo uses E, d [MMMM][MMM][M] u H:m:s Z which has three optional patterns for the month.

    Demo:

    import java.time.DateTimeException;
    import java.time.Instant;
    import java.time.format.DateTimeFormatter;
    import java.util.Locale;
    import java.util.stream.Stream;
    
    
    public class Main {
        public static void main(String[] args) {
            Stream.of(
                    "So., 18 Juli 2021 15:24:00 +0200",
                    "ven., 16 avr. 2021 15:24:00 +0200",
                    "vr, 16 apr. 2021 15:24:00 +0200",
                    "vr, 16 07 2021 15:24:00 +0200"
            ).forEach(s -> {
                Stream.of(
                        Locale.GERMANY,
                        Locale.FRANCE,
                        new Locale("nl", "NL")
                ).forEach( locale -> {
                    try {
                        System.out.println("Parsed '" + s + "' using the locale, " + locale + " => " + parseToInstant(s, locale));
                    }catch(DateTimeException e) {
                        //....
                    }
                });
            });
        }
    
        static Instant parseToInstant(String strDateTime, Locale locale) {
            return DateTimeFormatter.ofPattern("E, d [MMMM][MMM][M] u H:m:s Z").withLocale(locale).parse(strDateTime,
                    Instant::from);
        }
    }
    

    Output:

    Parsed 'So., 18 Juli 2021 15:24:00 +0200' using the locale, de_DE => 2021-07-18T13:24:00Z
    Parsed 'ven., 16 avr. 2021 15:24:00 +0200' using the locale, fr_FR => 2021-04-16T13:24:00Z
    Parsed 'vr, 16 apr. 2021 15:24:00 +0200' using the locale, nl_NL => 2021-04-16T13:24:00Z
    Parsed 'vr, 16 07 2021 15:24:00 +0200' using the locale, nl_NL => 2021-07-16T13:24:00Z
    

    ONLINE DEMO

    Learn more about the Date-Time patterns from DateTimeFormatterBuilder.