Reputation: 55
I am working on a school assignment and I am just stuck with the logic on this. Basically need to validate a RegEx (date) of years between 1900 and 2099. The days cannot exceed the maximum month days; (ie. June has 30 days so 31 is invalid) as well as account for leap years where the February date can be 29. Here is what I have so far but I keep getting validation errors from when the code is ran in the TestHarness. I think I have way to much logic here but not sure how to resolve. Any help would be awesome.
public class RegexValidator {
//class variables
private String DATE_REGEX = "^((19|20)\\d\\d)-(0?[1-9]|
1[012])-(0?[1-9]|[12][0-9]|3[01])$";
public RegexValidator() {
m_datePattern.compile(DATE_REGEX);
}
public boolean validDate(String date) {
Matcher matcher = m_datePattern.matcher(date);
int year = Integer.parseInt(matcher.group(1));//parse to calculate leap
String month = matcher.group(2);
String day = matcher.group(3);
if(matcher.matches()) {
matcher.reset();
if(matcher.find()) {
if(day.equals("31") && (month.equals("4") || month.equals("04") ||
month.equals("6") || month.equals("06") || month.equals("9") ||
month.equals("09") || month.equals("11"))) {
return false;
} else if(month.equals("2") || month.equals("02")) {
//accounts for 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;
}
}
Here is a list of the errors I am getting:
Error validating date '1900-1-11'
Error validating date '1900-1-11'
---- test date 1892-02-29 - expected false
---- Exception calling validDate: null
---- test date 1976-02-29 - expected true
---- Exception calling validDate: null
Error validating date '1976-02-29'
Error validating date '1976-02-29'
---- test date 2001-02-29 - expected false
---- Exception calling validDate: null
---- test date 2002-13-02 - expected false
---- Exception calling validDate: null
---- test date 2003-01-31 - expected true
---- Exception calling validDate: null
Error validating date '2003-01-31'
Error validating date '2003-01-31'
---- test date 1964-03-31 - expected true
---- Exception calling validDate: null
Error validating date '1964-03-31'
Error validating date '1964-03-31'
---- test date 1965-4-31 - expected false
---- Exception calling validDate: null
---- test date 1954-4-30 - expected true
---- Exception calling validDate: null
Error validating date '1954-4-30'
Error validating date '1954-4-30'
---- test date 1901-5-33 - expected false
---- Exception calling validDate: null
---- test date 1901-5-15 - expected true
---- Exception calling validDate: null
Error validating date '1901-5-15'
Error validating date '1901-5-15'
---- test date 2016-05-31 - expected true
---- Exception calling validDate: null
Error validating date '2016-05-31'
Error validating date '2016-05-31'
---- test date 2006-06-31 - expected false
---- Exception calling validDate: null
---- test date 20016-06-29 - expected false
---- Exception calling validDate: null
---- test date 1934-7-4 - expected true
---- Exception calling validDate: null
Error validating date '1934-7-4'
Error validating date '1934-7-4'
---- test date 2016-07-31 - expected true
---- Exception calling validDate: null
Error validating date '2016-07-31'
Error validating date '2016-07-31'
---- test date 2011-8-19 - expected true
---- Exception calling validDate: null
Error validating date '2011-8-19'
Error validating date '2011-8-19'
---- test date 2111-8-31 - expected false
---- Exception calling validDate: null
---- test date 2011-09-30 - expected true
---- Exception calling validDate: null
Error validating date '2011-09-30'
Error validating date '2011-09-30'
---- test date 2111-9-31 - expected false
---- Exception calling validDate: null
---- test date 2011-10-1 - expected true
---- Exception calling validDate: null
Error validating date '2011-10-1'
Error validating date '2011-10-1'
---- test date 2111-10-31 - expected false
---- Exception calling validDate: null
---- test date 2001-10-31 - expected true
---- Exception calling validDate: null
Error validating date '2001-10-31'
Error validating date '2001-10-31'
---- test date 2111-10-33 - expected false
---- Exception calling validDate: null
---- test date 2111-11-30 - expected false
---- Exception calling validDate: null
---- test date 2013-11-30 - expected true
---- Exception calling validDate: null
Error validating date '2013-11-30'
Error validating date '2013-11-30'
---- test date 2111-11-31 - expected false
---- Exception calling validDate: null
---- test date 2011-12-31 - expected true
---- Exception calling validDate: null
Error validating date '2011-12-31'
Error validating date '2011-12-31'
---- test date 2099-12-31 - expected true
---- Exception calling validDate: null
Error validating date '2099-12-31'
Error validating date '2099-12-31'
Upvotes: 2
Views: 1425
Reputation: 11884
I have a better solution (with Leap year):
public static final String DATE_FORMAT_REG_EXP = "(^(((0[1-9]|1[0-9]|2[0-8])[\\/](0[1-9]|1[012]))|((29|30|31)[\\/](0[13578]|1[02]))|((29|30)[\\/](0[4,6,9]|11)))[\\/](19|[2-9][0-9])\\d\\d$)|(^29[\\/]02[\\/](19|[2-9][0-9])(00|04|08|12|16|20|24|28|32|36|40|44|48|52|56|60|64|68|72|76|80|84|88|92|96)$)";
@Test
public void testCheckValidateDate() {
Assert.assertFalse("Wrong date, january do not have 32 days.", "32/01/2016".matches(DATE_FORMAT_REG_EXP));
Assert.assertFalse("Wrong date, February do not have 30 days.", "30/02/2016".matches(DATE_FORMAT_REG_EXP));
Assert.assertFalse("Wrong date, 2017 is not Leap year so 28 days", "29/02/2017".matches(DATE_FORMAT_REG_EXP));
Assert.assertFalse("Wrong date, november have 30 days.", "31/11/2016".matches(DATE_FORMAT_REG_EXP));
Assert.assertFalse("Wrong date, 16 instead of 2016.", "30/11/16".matches(DATE_FORMAT_REG_EXP));
Assert.assertTrue("Good date.", "31/01/2016".matches(DATE_FORMAT_REG_EXP));
Assert.assertTrue("Good date, 2016 is Leap year so 29 days", "29/02/2016".matches(DATE_FORMAT_REG_EXP));
Assert.assertTrue("Good date.", "28/02/2016".matches(DATE_FORMAT_REG_EXP));
Assert.assertTrue("Good date.", "28/02/2017".matches(DATE_FORMAT_REG_EXP));
Assert.assertTrue("Good date.", "30/11/2016".matches(DATE_FORMAT_REG_EXP));
}
Démo:
Regexp - java - javascript - php - python - C# - ruby - rust - goland - perl
Upvotes: 1
Reputation: 1535
There are in fact numerous things wrong with this code. Here are the ones that I've been able to spot:
matcher.group
before matcher.matches
or matches.find
. This is illegal and throws IllegalStateException
(see JavaDoc for this method here).(19|20)
is also a matching group, so group 2 will not correspond to the month, as you seem to assume, but to first two digits of the year.Your algorithm for checking leap years is too simple. Consider:
@Test
public void leapYearTricky() {
Assert.assertFalse(new RegexValidator().validDate("1900-02-29"));
}
Also, not an error per se, but what's the point of matcher.matches
, matcher.reset
, matcher.find
? Why isn't matcher.matches()
enough?
Upvotes: 1
Reputation: 31699
If m_datePattern
is a Pattern
, you're using compile
incorrectly. The signature of compile is
public static Pattern compile(String regex)
Since it's static
, it does not apply to an instance; it's normally called like
Pattern.compile(regex)
Using a Pattern
object instead of the class name makes no difference. Thus, if p
is a Pattern
object, then:
p.compile(regex)
does the exact same thing as Pattern.compile(regex)
, even if p
is null
.
The object is ignored.
Finally, compile
returns a Pattern
, which means the result has to be assigned to a Pattern
object:
pat = Pattern.compile(Regex);
Your code doesn't assign it anywhere. So the resulting pattern is just thrown away.
Finally, when you use group(n)
, the groups, starting at 1, are the capture groups beginning with the first (
, second (
, etc., in the regex. Your regex is
"^((19|20)\\d\\d)-(0?[1-9]|1[012])-(0?[1-9]|[12][0-9]|3[01])$"
In this regex, group(1)
is the year; group(2)
is 19 or 20; group(3)
is the month, and group(4)
is the day. Your code is using the wrong groups for the month and day. Either change the numbers, or designate (19|20)
as a non-capture group like this:
"^((?:19|20)\\d\\d)-(0?[1-9]|1[012])-(0?[1-9]|[12][0-9]|3[01])$"
Now it won't be counted as one of the capture groups.
There may be other errors in your code. These are just the ones I noticed.
Upvotes: 1