Search code examples
javajava-8datetime-formatdatetime-parsingjava-time

How to check if string matches date pattern using time API?


My program is parsing an input string to a LocalDate object. For most of the time the string looks like 30.03.2014, but occasionally it looks like 3/30/2014. Depending on which, I need to use a different pattern to call DateTimeFormatter.ofPattern(String pattern) with. Basically, I need to check if the string matches the pattern dd.MM.yyyy or M/dd/yyyy before doing the parsing.

The regex approach would be something like:

LocalDate date;
if (dateString.matches("^\\d?\\d/\\d{2}/\\d{4}$")) {
  date = LocalDate.parse(dateString, DateTimeFormatter.ofPattern("M/dd/yyyy"));  
} else {
  date = LocalDate.parse(dateString, DateTimeFormatter.ofPattern("dd.MM.yyyy"));  
}

This works, but it would be nice to use the date pattern string when matching the string also.

Are there any standard ways to do this with the new Java 8 time API, without resorting to regex matching? I have looked in the docs for DateTimeFormatter but I couldn't find anything.


Solution

  • Okay I'm going ahead and posting it as an answer. One way is to create the class that will holds the patterns.

    public class Test {
        public static void main(String[] args){
            MyFormatter format = new MyFormatter("dd.MM.yyyy", "M/dd/yyyy");
            LocalDate  date = format.parse("3/30/2014"); //2014-03-30
            LocalDate  date2 = format.parse("30.03.2014"); //2014-03-30
        }
    }
    
    class MyFormatter {
        private final String[] patterns;
    
        public MyFormatter(String... patterns){
            this.patterns = patterns;
        }
    
        public LocalDate parse(String text){
            for(int i = 0; i < patterns.length; i++){
                try{
                    return LocalDate.parse(text, DateTimeFormatter.ofPattern(patterns[i]));
                }catch(DateTimeParseException excep){}
            }
            throw new IllegalArgumentException("Not able to parse the date for all patterns given");
        }
    }
    

    You could improve this as @MenoHochschild did by directly creating an array of DateTimeFormatter from the array of String you pass in the constructor.


    Another way would be to use a DateTimeFormatterBuilder, appending the formats you want. There may exists some other ways to do it, I didn't go deeply through the documentation :-)

    DateTimeFormatter dfs = new DateTimeFormatterBuilder()
                               .appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd"))                                                                 
                               .appendOptional(DateTimeFormatter.ofPattern("dd.MM.yyyy"))                                                                                     
                               .toFormatter();
    LocalDate d = LocalDate.parse("2014-05-14", dfs); //2014-05-14
    LocalDate d2 = LocalDate.parse("14.05.2014", dfs); //2014-05-14