Question

I would like to validate a strictly formatted "time". This "time" is of the following form:

\d+d \d+h \d+m

where "d" represents days, "h" represents hours, and "m" represents minutes and each number has a minimum value of "1". The main concern is that each substring may or may not exist, but there will always be at least one. Additionally, they must be in the order specified above.

Is my following RegEx the best way to validate the format? Is RegEx the best balance between conciseness and speed?

(?=.+)^(?:(?:[1-9]|[1-9][0-9]+)d\s?)?(?:(?:[1-9]|1[0-9]|2[0-3])h\s?)?(?:(?:[1-9]|[1-5][0-9])m)?$

I've included the lookahead to ensure an empty string does not match.

The only minor issue I see is that something like "23h " would match if there isn't a proceeding "m" value. The same goes for "d".

Was it helpful?

Solution

Here is an optimised pattern that checks strictly the format you describe:

^(?=\S)(?:[1-9][0-9]*d)?(?:(?:^| )(?:1[0-9]?|[3-9]|2[0-3]?)h)?(?:(?:^| )(?:[1-5][0-9]?|[6-9])m)?$

Details:

(?=\S) ensures that there is at least one group in the pattern and forces the string to not begin with a space. (note that you only need to find one character)

[1-9][0-9]*d is faster than (?:[1-9]|[1-9][0-9]+)d since the character class [1-9] is tested only once.

(?:1[0-9]?|[3-9]|2[0-3]?) a bit longer than (?:[1-9]|1[0-9]|2[0-3]) but more efficient since the first digit is tested only once. Alternatives are sorted by probability (11/22 for the first, 7/22 for the second, 4/22 for the last)

The same for [1-5][0-9]?|[6-9].

I have assumed that groups must be separated with a space. To ensure that, I have removed \s? at the end of the groups 1 and 2 to put (?:^| ) at the begining of the groups 2 and 3. There is only two possibilities: the group is at the begining or there is an other group before and a space (remember that you can't have a space and no group before due to the lookahead)

You obtain in fine a pattern a little longer (one character) but faster and more binding. If you need for an obscure reason to reduce the size of the pattern, you can gain 3 characters using the old subpatterns for numbers in group 2 and 3.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top