In your month regex, you're allowing a single-digit to match first and-so it does (and then stops). Try moving the required-two-digit month to check first and then the single digit:
(?:0?[1-9]|1[0-2])
should become:
(?:1[0-2]|0?[1-9])
UPDATE (reasoning)
The reason why the same pattern, leading with 0?
, in the day
pattern works but doesn't in the month
pattern is because you specify that there are characters that have to follow the day
pattern - therefore, the entire pattern for the day
is processed. In the month
pattern, however, there are no characters specified to follow; therefore, it stops upon finding a first match which, in the original pattern, was a single digit.
If you were to reverse the input format (i.e. instead of dd/mm
you used mm/dd
) and simply swapped sDay
and sMonth
in the compiled regex, you'll actually notice that the month
would properly match two numbers and the day
would fail instead!
One way to resolve the issue is by matching the two-character rule first and then the optional single-character, like my answer suggests. An alternative method would assume/require that your input date is on a line by itself (i.e. the date starts at the beginning of the line and ends at the end of the line with no other text). If this is true, you can use regex's ^
and $
characters to match the beginning and end of the line, respectively:
Pattern.compile("^(" + sDay + ")" + "(?:" + sSeparators + ")" + "(" + sMonth+ ")$");
Doing this, it will evaluate each pattern completely to find the full match and, in this case, you should always match the correct month/day.
SITE NOTE (suggestion, not answer-specific though)
Per a useful comment/suggestion by @MarkoTopolnik, you don't need to use the non-capturing group around each group (months + days), especially since you immediately wrap them in a capturing group rendering the non-capturing group useless. So, the above pattern could simply become:
1[0-2]|0?[1-9]