I am doing the following programming exercise: regex validation of 24 hours time. The statement is:
Write a regex to validate a 24 hours time string. See examples to figure out what you should check for:
Accepted: 01:00 - 1:00
Not accepted:
24:00
You should check for correct length and no spaces.
I would like to ask, why the following regular expression, matches 24:00
public class RegexValidation {
public static boolean validateTime(String time) {
System.out.println("time: "+time);
return time.matches("(?:^[2])[0123]+:[0-5]+[0-9]|[0-9]+:[0-5]+[0-9]");
}
}
Because I thought it was expressing: "If string starts with 2, then it should continue with [0-3] (one or more) : [0-5] one or more and [0-9]. Else it continues with [0-9] one or more : [0-5] one or more and [0-9]."
The tests are:
import org.junit.Test;
import static org.junit.Assert.*;
public class RegexValidationTest {
@Test
public void test1() {
assertTrue(RegexValidation.validateTime("01:00"));
}
@Test
public void test2() {
assertTrue(RegexValidation.validateTime("1:00"));
}
@Test
public void test3() {
assertTrue(RegexValidation.validateTime("00:00"));
}
@Test
public void test4() {
assertFalse(RegexValidation.validateTime("13:1"));
}
@Test
public void test5() {
assertFalse(RegexValidation.validateTime("12:60"));
}
@Test
public void test6() {
assertFalse(RegexValidation.validateTime("24:00"));
}
}
In addition I wrote the following solution, which passes the tests:
public class RegexValidation {
public static boolean validateTime/*⌚*/(String time) {
if(time.matches("[\\d]+:[\\d]{2}")){
String[] times = time.split(":");
int hours = Integer.parseInt(times[0]);
int minutes = Integer.parseInt(times[1]);
return hours < 24 && minutes < 60;
}
return false;
}
}
I have also read:
Finally the question is, why in the first code the regex matches 24:00?‽
This is because of the | present. The alternative after this, [0-9]+ matches any digit from 1 to 9, and breaks the required output.
The following regex should work,
^([01]\d|[0-9]|2[0-3]):?([0-5]\d)$
If the : is not optional, remove the ?
^([01]\d|[0-9]|2[0-3]):([0-5]\d)$
Also verified on jshell
jshell> var pattern = Pattern.compile("^([01]\\d|[0-9]|2[0-3]):?([0-5]\\d)$");
pattern ==> ^([01]\d|[0-9]|2[0-3]):?([0-5]\d)$
jshell> pattern.matcher("23:01").matches();
$2 ==> true
jshell> pattern.matcher("24:01").matches();
$3 ==> false
jshell> pattern.matcher("00:01").matches();
$4 ==> true
jshell> pattern.matcher("09:01").matches();
$5 ==> true
jshell> pattern.matcher("9:01").matches();
$6 ==> true
jshell> pattern.matcher("12:00").matches();
$7 ==> true
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With