Home > Back-end >  Regex for validating date format DD.MM.YYYY
Regex for validating date format DD.MM.YYYY

Time:11-12

The task is following:

Build the regular expression for following validation: a) Date (Format: DD.MM.YYYY)

I wrote the following code:

package validator.utils;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Validator {
        
    public static boolean checkDateFormatEU(String str) {
        //* Date (Format: DD.MM.YYYY)*/
        final String regexDateFormat = "^\\d{2}\\.\\d{2}\\.\\d{4}$";
        if (str == null || !(Pattern.matches(regexDateFormat, str) ) ) {
            return false;
        }
        String year = str.substring(6, 9);
        //*Range from 1100 to current century*/
        final String REGEX_31_DAY_MONTHS = "(0[1-9]|[12][0-9]|3[01])[\\.](0[13578]|1[02])[\\.](10|11|12|13|14|15|16|17|18|19|20)[0-9]{2}";
        final String REGEX_30_DAY_MONTHS = "(0[1-9]|[12][0-9]|30)[\\.](0[469]|11)[\\.](10|11|12|13|14|15|16|17|18|19|20)[0-9]{2}";
        final String REGEX_FEB_29_DAY_MONTHS = "29[\\.](02)[\\.](((10|11|12|13|14|15|16|17|18|19|20)(04|08|[2468][048]|[13579][26]))|2000)";
        final String REGEX_FEB_1_28_DAY_MONTHS = "(0[1-9]|1[0-9]|2[0-8])[\\\\.](02)[\\\\.](10|11|12|13|14|15|16|17|18|19|20)[0-9]{2}";
        final String REGEX_LEAP_YEAR = "(("   REGEX_31_DAY_MONTHS   ")|("   REGEX_30_DAY_MONTHS   ")|("   
                                       REGEX_FEB_29_DAY_MONTHS   ")|("   REGEX_FEB_1_28_DAY_MONTHS   "))";
        final String REGEX_NON_LEAP_YEAR = "(("   REGEX_31_DAY_MONTHS   ")|("   REGEX_30_DAY_MONTHS   ")|("   
                                           REGEX_FEB_1_28_DAY_MONTHS   "))";
        final String CURRENT_REGEX =  isLeapYear(year) ? REGEX_LEAP_YEAR
                                                       : REGEX_NON_LEAP_YEAR;
        Pattern p = Pattern.compile(CURRENT_REGEX);
        Matcher m = p.matcher(str);
        return m.matches();
    }
    
    public static boolean isLeapYear(String str) {
        boolean yearIsLeap = false;
        int year = Integer.valueOf(str);
        if ( ( ( year % 4 == 0 ) && ( year % 100 != 0 ) ) || ( year % 400 == 0 ) ) {
            yearIsLeap = true;
        }
        return yearIsLeap;
    }
}

The question are following: How this code can be optimized? Condition: regular expressions must be used.

CodePudding user response:

Rather than using pure regex and having to worry about edge cases like leap years, a better approach would be to just parse the input string using the specified format.

public static boolean checkDateFormatEU(String str) {
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd.MM.yyyy", Locale.ENGLISH);
    try {
        LocalDate.parse(str, formatter);
    }
    catch (DateTimeParseException e) {
        System.out.println("Invalid date: "   str);
        return false;
    }

    return true;
}

If the input date cannot be parsed using your expected date format, then LocalDate#parse() would throw an exception, which returns a false result. Otherwise, true would be returned.

CodePudding user response:

Condition: regular expressions must be used. - Well there's your problem!!

This is not a good use-case for regexes. They won't give you an efficient solution. They certainly won't give you a good1 solution.

But if you want to optimize this, consider precompiling the two regexes and saving the compiled versions in static variables.


1 - OK, that is my opinion. But I suspect that the vast majority of experienced Java programmers would agree. Use the java.time.format classes to do your validation. That's what they are designed for.

  • Related