Java conditional regular expression check 24 hours time? ‽
I’m 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.
Excuse me, why does the following regular expression match 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 think it’s saying:
“If the string starts with 2, it should continue with [0-3] (one or more): [0-5] one or more and [0-9]. Otherwise it continues with [0-9] one or more: [0-5] one or more and [0-9]. ”
The test is:
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"));
}
}
Also I wrote the following solution and passed the test:
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’ve seen it too:
- Conditional Regular Expression in Java ?
- https://www.regular-expressions.info/conditional.html
- understanding regex if then statements
The final question is, why does the regular expression match 24:00 in the first code? ‽
Solution
This is because |
exists. After this alternative [0-9]+
matches any number from 1 to 9 and interrupts the desired output.
following regex should do
,
^([01]\d|[ 0-9]|2[0-3]):? ([0-5]\d)$
If :
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