0

I have been scouring the internet for a way of doing 12/24 hour time format only ( _ _ : _ _ with no AM/PM) validation. The requirement is that it must actively prevent keypresses that would invalidate the time. It also must accept either 1 or 2 digits before the colon not over 23 and require 2 digits after it no over 59.

I have used both jquery inputmask and maskedinput to no avail. Whatever I try they just don't behave exactly right.

I finally found this article http://blog.pierrejeanparra.com/2011/10/time-input-mask-regexp-powered/ that contains some good logic and results in an almost perfect regexp that can be tied in with regexp mask to get the desired behavior. Unfortunately there is just one tiny bug left in this expression that I have been racking my brains over and just cannot figure out. The expression is as follows

/^(([0-1][0-9]|2[0-3]|[0-9])|([0-1][0-9]|2[0-3]|[0-9])(:)[0-5]?[0-9]?)$/

The problem remaining with it is that it allows 1:6 because the [0-5] is optional. If I try to remove ? after [0-5] then the : doesn't work anymore. Help would be very appreciated. I know this is a common problem that doesn't seem to have any perfectly working solutions.

Here is a plnkr that demonstrates

http://plnkr.co/edit/OE6PGTuCvQa380S7b8Zg?p=preview

Josh
  • 1,648
  • 8
  • 27
  • 58
  • Removing both question marks should work. If you want it to require the colon followed by minutes (currently it looks like it can accept just hours or hours:minutes), delete the first part `([0-1][0-9]|2[0-3]|[0-9])|` – Reinstate Monica -- notmaynard Oct 15 '13 at 15:16
  • 3
    Data validation is one thing. User experience is another. I find that sites or programs that that enforce strong restrictions often irritate me because of some error. Why validate live? Why not just validate on submission or on blur and turn the field red instead of actively preventing key presses? – Corey Ogburn Oct 15 '13 at 15:19
  • Well the user experience is actually great for this regexp. The requirements from the client are very strict and unfortunately the validation needs to happen in place. – Josh Oct 15 '13 at 15:23
  • There's more than "one tiny bug" here. [visual](http://www.regexper.com/#%5E%28%28%5B0-1%5D%5B0-9%5D%7C2%5B0-3%5D%7C%5B0-9%5D%29%7C%28%5B0-1%5D%5B0-9%5D%7C2%5B0-3%5D%7C%5B0-9%5D%29%28%3A%29%5B0-5%5D%3F%5B0-9%5D%3F%29%24). Do you really want to allow `0`-`9`, `10`-`23` (without the colon)? How about `0:-23:`, with nothing after? And I think it's a bad idea to allow just one digit after the colon. – Kevin Oct 15 '13 at 15:24
  • Right, I missed the part that you were checking as the user typed. Filter with the regex you have, then (on submission) check against the modified regex as suggested previously. – Reinstate Monica -- notmaynard Oct 15 '13 at 15:24
  • I attempted to remove both ? marks and the result it it no longer allows the colon. Let me see if I can create a plnkr to demonstrate. – Josh Oct 15 '13 at 15:24
  • yes all of those cases are just fine. I just need it to not accept a 6 after the colon. – Josh Oct 15 '13 at 15:26
  • You'll need one regex to check that the time being typed is on its way to being valid (the one you currently have), and another one to confirm on submission that the string _is_ valid. – Reinstate Monica -- notmaynard Oct 15 '13 at 15:26
  • Please check out the plnkr. – Josh Oct 15 '13 at 15:28
  • 1
    I think the problem you are encountering is that not every substring of a valid time is itself a valid time (in fact, most aren't). Therefore, you cannot use a single regex to check that the field is always valid. – Kevin Oct 15 '13 at 15:30
  • Have you even looked at the plnkr? Obviously a single regexp can and does work well since it is working right there. There is just one minor issue that needs to be fixed which is allowing a 6 after the : – Josh Oct 15 '13 at 15:35
  • Unfortunately, the plnkr is not demonstrating the problem. Or anything, really. – Reinstate Monica -- notmaynard Oct 15 '13 at 16:05
  • How is it not demonstrating the problem? It prevents you from typing any invalid time or any characters besides 0-9 and : It only allows valid times, except that it allows 1:6. I don't understand how that demonstrates nothing when that it the entire problem. – Josh Oct 15 '13 at 17:05

2 Answers2

0

Here was the answer if anyone is interested.

^((([0-1][0-9]|2[0-3]|[0-9])|([0-1][0-9]|2[0-3]|[0-9])(:|h)|([0-1][0-9]|2[0-3]|[0-9])|([0-1][0-9]|2[0-3]|[0-9])(:|h)[0-5][0-9]?))$
Josh
  • 1,648
  • 8
  • 27
  • 58
0

How about this simple one:

^(?:[01]?\d|2[0-3]):[0-5]?\d$

Explanation:

The regular expression:

(?-imsx:^(?:[01]?\d|2[0-3]):[0-5]?\d$)

matches as follows:

NODE                     EXPLANATION
----------------------------------------------------------------------
(?-imsx:                 group, but do not capture (case-sensitive)
                         (with ^ and $ matching normally) (with . not
                         matching \n) (matching whitespace and #
                         normally):
----------------------------------------------------------------------
  ^                        the beginning of the string
----------------------------------------------------------------------
  (?:                      group, but do not capture:
----------------------------------------------------------------------
    [01]?                    any character of: '0', '1' (optional
                             (matching the most amount possible))
----------------------------------------------------------------------
    \d                       digits (0-9)
----------------------------------------------------------------------
   |                        OR
----------------------------------------------------------------------
    2                        '2'
----------------------------------------------------------------------
    [0-3]                    any character of: '0' to '3'
----------------------------------------------------------------------
  )                        end of grouping
----------------------------------------------------------------------
  :                        ':'
----------------------------------------------------------------------
  [0-5]?                   any character of: '0' to '5' (optional
                           (matching the most amount possible))
----------------------------------------------------------------------
  \d                       digits (0-9)
----------------------------------------------------------------------
  $                        before an optional \n, and the end of the
                           string
----------------------------------------------------------------------
)                        end of grouping
----------------------------------------------------------------------
Toto
  • 89,455
  • 62
  • 89
  • 125