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

user1019830 picture user1019830 · May 6, 2014 · Viewed 21k times · Source

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.

Answer

Alexis C. picture Alexis C. · May 6, 2014

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