UK Date Regular Expression [duplicate]
I'm trying to create a regular expression that validates UK date format. I have the following:
(0[1-9]|[12][0-9]|3[01])[- /.](0[1-9]|1[012])[- /.](19|20)\d\d
This works great for validating: 09/12/2011. But if the date is: 9/12/2011 it will not validate correctly. Is there a regular expression that allows me to use a single number and two numbers for the day section? For example "09" and "9".
Just make the leading 0
optional:
(0?[1-9]|[12][0-9]|3[01])[- /.](0?[1-9]|1[012])[- /.](19|20)\d\d
You will need an additional validation step, though - this regex of course won't check for invalid dates like 31-02-2000
etc. While it's possible to do this in regex, it's not recommended because it's much easier to do this programmatically, and that regex is going to be monstrous. Here is a date validating regex (that uses the mmddyyyy format, though) to show what I mean.
My preference goes to a combination of the simple regex, (\d{1,2})[-/.](\d{1,2})[-/.](\d{4})
, with some code that validates that this is indeed a correct date. You will have to have that code anyways, unless you want to make a monstrous regex that rejects "29-02-2011" but not "29-02-2008".
Anyway, here's a breakdown of that regex so you can see what's going on:
\d{1,2}
: this part matches one or two ({1,2}
) digits (\d
), making up the day portion of the date.[-/.]
: this matches one of the characters inside the brackets, i.e, either a.
, a/
, or a-
.\d{1,2}
: again, this matches one or two digits from the month.[-/.]
: another separator...\d{4}
: this matches exactly four ({4}
) digits for the year portion.
Note that the day, month, and year portion of the regular expression are inside parentheses. This is to create groups. Each of those three portions will be captured into a group that you can retrieve from the match. Groups are identified with a number, starting with 1, from left to right. This means that the day will be group 1, the month group 2, and the year group 3. There is also a group 0 that always contains the entire text matched.
You can use the groups to perform the second part of the validation and reject invalid dates like "30-02-2011", "31-4-2011", or "32-13-2011".
If you want to reject inputs that use two different separators, like "31-12.2011", you can use a slightly more advanced feature called backreferences:
(\d{1,2})([-/.])(\d{1,2})\2(\d{4})
Note that now I placed the first separator inside a group. This changes the month to group 3, and the year to group 4. The separator is matched by group 2. The backreference is that \2
part between the month and the year. It matches whatever was matched by the 2nd previous group. If you walk back two groups from the backreference you end up in group 2, the separator. If that group matched a .
, the backreference with match only a .
as well; if it matched a -
, the backreference will match only a -
; and so on.
What is "the UK date format" anyway?
Officially, it's 2011-02-21 today, see BS EN 28601 / ISO 8601.
On the web, you should all be using the format defined in RFC 3339.
Correct way to check for the day is to ban the [4-9].
numbers too.
Something like 0[0-9]|[12][0-9]|3[01]|[^0-9][0-9]|^[0-9]
Yes. {n,m}
is the quantifier that say "at least n element, max m elements". So you can write \d{1,2}
(matches 1 or 2 digits). Complete date: \d{1,2}/\d{1,2}/\d{4}
Alternative: Make the leading zero optional:
0?\d/0?\d/\d{4}
The question mark says, that the element before the question mark is optional.
Use this code, I am validating everything for the date. :-
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class FinalDateValidator {
private Pattern pattern;
private Matcher matcher;
public boolean isValidDate(final String date) {
Pattern pattern;
Matcher matcher;
final String DATE_PATTERN = "([0-9]{4})/(0?[1-9]|1[012])/(0[1-9]|[12][0-9]|3[01]|[1-9])";
pattern = Pattern.compile(DATE_PATTERN);
matcher = pattern.matcher(date);
if (matcher.matches()) {
matcher.reset();
if (matcher.find()) {
int year = Integer.parseInt(matcher.group(1));
String month = matcher.group(2);
String day = matcher.group(3);
System.out.println("__________________________________________________");
System.out.println("year : "+year +" month : "+month +" day : "+day);
if (day.equals("31")
&& (month.equals("4") || month.equals("6")
|| month.equals("9") || month.equals("11")
|| month.equals("04") || month.equals("06") || month
.equals("09"))) {
return false; // only 1,3,5,7,8,10,12 has 31 days
} else if (month.equals("2") || month.equals("02")) {
// leap year
if (year % 4 == 0) {
if (day.equals("30") || day.equals("31")) {
return false;
} else {
return true;
}
} else {
if (day.equals("29") || day.equals("30")
|| day.equals("31")) {
return false;
} else {
return true;
}
}
} else {
return true;
}
} else {
return false;
}
} else {
return false;
}
}
public static void main(String argsp[]){
FinalDateValidator vs = new FinalDateValidator();
System.out.println("1: 1910/12/10---"+vs.isValidDate("1910/12/10"));
System.out.println("2: 2010/2/29---"+vs.isValidDate("2010/02/29"));
System.out.println("3: 2011/2/29---"+vs.isValidDate("2011/02/29"));
System.out.println("3: 2011/2/30---"+vs.isValidDate("2011/02/30"));
System.out.println("3: 2011/2/31---"+vs.isValidDate("2011/02/31"));
System.out.println("4: 2010/08/31---"+vs.isValidDate("2010/08/31"));
System.out.println("5: 2010/3/10---"+vs.isValidDate("2010/03/10"));
System.out.println("6: 2010/03/33---"+vs.isValidDate("2010/03/33"));
System.out.println("7: 2010/03/09---"+vs.isValidDate("2010/03/09"));
System.out.println("8: 2010/03/9---"+vs.isValidDate("2010/03/9"));
System.out.println("9: 1910/12/00---"+vs.isValidDate("1910/12/00"));
System.out.println("10: 2010/02/01---"+vs.isValidDate("2010/02/01"));
System.out.println("11: 2011/2/03---"+vs.isValidDate("2011/02/03"));
System.out.println("12: 2010/08/31---"+vs.isValidDate("2010/08/31"));
System.out.println("13: 2010/03/39---"+vs.isValidDate("2010/03/39"));
System.out.println("14: 201011/03/31---"+vs.isValidDate("201011/03/31"));
System.out.println("15: 2010/032/09---"+vs.isValidDate("2010/032/09"));
System.out.println("16: 2010/03/922---"+vs.isValidDate("2010/03/922"));
}
}
Enjoy...
I ran into the similar requirements. Here is the complete regular expression along with Leap Year validation. Format: dd/MM/yyyy
(3[01]|[12]\d|0[1-9])/(0[13578]|10|12)/((?!0000)\d{4})|(30|[12]\d|0[1-9])/(0[469]|11)/((?!0000)\d{4})|(2[0-8]|[01]\d|0[1-9])/(02)/((?!0000)\d{4})| 29/(02)/(1600|2000|2400|2800|00)|29/(02)/(\d\d)(0[48]|[2468][048]|[13579][26])
It can be easily modified to US format or other EU formats.
精彩评论