views:

215

answers:

2

I need a regex which restricts an hour entry from 0-24 with the fraction in multiples of .25. Please keep in mind the following conditions must be met:

  • When whole part is 0-23, the fractional part can be .0, .25, .5, or .75
  • When whole part is 24, the fractional part can be .0
  • When no whole part is present, the fractional part must be .0, .25, .5, or .75
  • Empty string is not allowed

I am very confident that the following expression can be tightened up, but this is what is in place thus far:

(^(([0-9])|(1[0-9])|(2[0-3]))(\.((0*)|(250*)|(50*)|(750*)))?$)|(^24(\.0*)?$)|(^\.((0+)|(250*)|(50*)|(750*))$)

Update: The regex validation exists both on the client (javascript) and server (asp.net, c#).

+11  A: 

And the reason why you absolutely, positively need to do this as a regular expression is why? Converting to a number and doing a few basic checks would be far easier.

Check if the number multiplied by 4 is a natural number <= 96, done.

Judging by your profile you're probably using .NET. I assume you want this as a regular expression because you're using a it for client side validation. I would seriously consider using a CustomValidator with a client side JavaScript.

Something along these lines for the JavaScript:

<script type="text/javascript">
function checkDuration(text)
{
    var tmp = parseFloat(text) * 4;
    return tmp >= 0 && tmp <= 96 && Math.ceil(tmp) == tmp;
}
</script>

Edit: I was slightly concerned about rounding errors when using floats, but it seems to work out okay for all possible cases.

Thorarin
+1: Yeah, even if it was searching for a number matching the criteria in a string (which it isn't, judging by the anchors), it would still be better to just match numbers and do the validation in a callback function.
Blixt
@Thorarin - Good idea. To answer your question, Regex seemed like a reasonable option to me. The validation exists both on the client (javascript) and server (asp.net, c#). Thanks.
Ben Griswold
Good thing I was writing a JavaScript implementation that you can adapt for your CustomValidator then :)
Thorarin
This will work perfectly. Thanks.
Ben Griswold
The reason rounding errors aren't a problem is that all your fractions (0, 0.25, 0.5, 0.75) are sums-of-integer-powers-of-two.
caf
@caf: yeah, I realized that later as well. But I'm sleepy and somewhat intoxicated :P I decided to just try the 3 fractional cases..
Thorarin
This reminds me The Old New Thing: How do I write a regular expression that matches an IPv4 dotted address? http://blogs.msdn.com/oldnewthing/archive/2006/05/22/603788.aspx
Pavel Chuchuva
+3  A: 
^((1?\d|2[0-3])?(\.(0|[27]?5)0*)|(1?\d|2[0-4])(\.0*)?)$
Laurence Gonsalves
+1 for effort. I like this one better because it doesn't use lookbehind assertion. Makes it easier to read and syntactically compatible with more regex implementations.
Thorarin
+1 - Nicely done, that's a lot better than my attempt. I'm going to delete mine in favor of this.
Tomalak