Search code examples
javaregexvalidationlocaldatetimedatetimeformatter

Regex validates fine with online tool, but not in java application


I have this regex used in Java as shown below:

private static final String DATE_TIME_REGEX = "^(20[1-5]\\d)-(0?[1-9]|1[012])-(0?[1-9]|[12]\\d|3[01])\\s([0-1]\\d)|(2[0-3]):([0-5]\\d):([0-5]\\d)$";

public static boolean validateDate(String dateStr) {
    return dateStr.matches(DATE_TIME_REGEX);
}

...to validate a date in this format:

private static final DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    String formattedDate = dateTimeFormatter.format(LocalDateTime.now());

...using this online tool

https://regexr.com/

...where adding this regex:

^(20[1-5]\d)-(0?[1-9]|1[012])-(0?[1-9]|[12]\d|3[01])\s([0-1]\d)|(2[0-3]):([0-5]\d):([0-5]\d)$

...works fine to validate a date string like:

2022-11-02 00:00:00

... but fails to validate (with no indication of the specifics) using the aforementioned validation code in java

To rule out the only caveat I can think of - when adding the code from the online tool into the java code, I have to add an extra \ before the other backslashes in the regex pattern when moving it from the online tool, i.e. \d and \s -> \\d and \\s. However, am highly dubious as to whether that is the issue


Solution

  • The pattern contains one group and alternation that look to be out of place:

    ^(20[1-5]\d)-(0?[1-9]|1[012])-(0?[1-9]|[12]\d|3[01])\s([0-1]\d)|(2[0-3]):([0-5]\d):...
                                                          ^ HERE > ^
    

    This makes your current pattern match regex101

    • EITHER the left part of the alternation from start up to the [0-1]\d hours-part
    • OR the right part from the 2[0-3] hours-part until the end

    Using this with matches() cannot work because it gets matched against the full string:

    public boolean matches()
    Attempts to match the entire region against the pattern.
    If the match succeeds then more information can be obtained...


    Refactored by fixing the structure it works fine (using matches, the ^ and $ are redundant).

    20[1-5]\d-(?:0?[1-9]|1[012])-(?:0?[1-9]|[12]\d|3[01])\s(?:[0-1]\d|2[0-3]):[0-5]\d:[0-5]\d
    

    See this Java demo at tio.run or a demo at regex101 (pattern explained and code generator)