There is no concept for "minimum value" of a regex, since it's only doing pattern matching, not reasoning about what the pattern represents. However, you can just exclude a certain pattern from being matched. If you don't want 00:00
then you can remove that from being valid.
Negative lookahead
The easiest way to modify your regular expression is to add a negative lookahead using the (?!)
syntax. If you don't want to match 00:00
then you can say (?!00:00)
. Your regular expression then needs to be:
^$|^(?!00:00)(([01][0-9])|(2[0-3])):[0-5][0-9]$
See on Regex101
const regex = /^$|^(?!00:00)(([01][0-9])|(2[0-3])):[0-5][0-9]$/;
const times = [
"00:01",
"00:10",
"01:00",
"12:01",
"13:01",
"23:59",
"00:00",
"23:60",
"24:00",
];
for (const time of times) {
test(time, regex);
}
function test(time, regex) {
const result = regex.test(time);
console.log(`result for [${time}] is [${result}]`);
}
Non-matching pattern
You can alternatively craft your pattern to avoid matching 00:00
outside of using negation. This is slightly more tedious as it makes the pattern bigger. Still, it's useful to know:
(([01][0-9])|(2[0-3])):[0-5][0-9]
will match anything and to avoid 00:00
you have to be very explicit by specifying anything but a pattern than matches it:
^$|^(00:0[1-9]|00:[1-5][0-9]|0[1-9]:[0-5][0-9]|(1[0-9]|2[0-3]):[0-5][0-9])$
See on Regex101
Now the pattern explicitly matches everything except 00:00
. As you see, it's quite longer and more annoying to read. I wouldn't recommend it but it's sometimes useful.
const regex = /^$|^(00:0[1-9]|00:[1-5][0-9]|0[1-9]:[0-5][0-9]|(1[0-9]|2[0-3]):[0-5][0-9])$/;
const times = [
"00:01",
"00:10",
"01:00",
"12:01",
"13:01",
"23:59",
"00:00",
"23:60",
"24:00",
];
for (const time of times) {
test(time, regex);
}
function test(time, regex) {
const result = regex.test(time);
console.log(`result for [${time}] is [${result}]`);
}
The best regex trick
This is the name of the technique from the article The Best Regex Trick. It's similar to using a negative lookahead since it allows you to discard certain matches but it's done only using alternation |
. You have to add the pattern(s) you don't want first then |
then finally capture the pattern you want using a capturing group ()
.
^$|^00:00$|^((?:[01][0-9]|2[0-3]):[0-5][0-9])$
See on Regex101 (00:00
is highlighted but not captured - see "Match information" on the right)
I've modified your pattern slightly to remove unneeded capturing groups, so you only get a single capture at most. This way you can check whether that was extracted:
const regex = /^$|^00:00$|^((?:[01][0-9]|2[0-3]):[0-5][0-9])$/;
const times = [
"00:01",
"00:10",
"01:00",
"12:01",
"13:01",
"23:59",
"00:00",
"23:60",
"24:00",
];
for (const time of times) {
test(time, regex);
}
function test(time, regex) {
const match = regex.exec(time);
const result = Boolean(match && match[1]);
// ^^ you can use the ?? operator for most newer environments *
console.log(`result for [${time}] is [${result}]`);
}
This is a slight overkill here because the negative lookahead can do the same. I'm including it here mostly to raise awareness of its existence. The technique is very useful in other circumstances where you need to only match some cases but not all, since it allows you to "discard" what you don't like and capture the rest. It's exceptionally easy, since it follows a very simple rule discard this|discard this, too|(keep this)
- anything you don't want is added at the front, and the pattern you want is in a capturing group at the end.
Use code
You can just reject data using normal code, rather than pattern matching.
const regex = /^$|^(([01][0-9])|(2[0-3])):[0-5][0-9]$/;
const times = [
"00:01",
"00:10",
"01:00",
"12:01",
"13:01",
"23:59",
"00:00",
"23:60",
"24:00",
];
for (const time of times) {
test(time, regex);
}
function test(time, regex) {
let result = false;
if (time != "00:00") {
result = regex.test(time);
}
console.log(`result for [${time}] is [${result}]`);
}