简体   繁体   中英

Javascript regex for validating 12 hour time

I'm trying to build a 12 hour input component in Javascript and I want to validate the format in real time, as the user types, like a parser validates incoming tokens.

I'm using react, so in each render the field value gets passed trhough the following regex:

const validTime = /(0[1-9])|(1[0-2]):([0-5][0-9])\s((a|p|A|P)(m|M))/;

I test if the value is valid, if not I add a red border to the input, but with this approach I can write anything, it wouldn't get submitted but you could write something like ajsjjsdf , and I'm looking for something different. Allow the user to type only the characters allowed by the regex rule above in real time.

Edit:

I'm adding some code...

Basically the input simpliefied is:

<input
  ref={(input) => {this[keyName] = input}}
  className="form-control"
  placeholder="09:00 AM"
  value={scheduleTime ? scheduleTime.value : ''}
  onChange={(ev) => this.onChangeTimeSchedule(ev, keyName)}/>

And the value handler:

  onChangeTimeSchedule = (ev, scheduleKey) => {
    const validChar = /[0-9]|[aApPmM]|[\s\b]|:/;
    const validTime = /(0[1-9])|(1[0-2]):([0-5][0-9])\s((a|p|A|P)(m|M))/;
    const { value } = ev.target;
    if(!validTime.test(value))
      return;

    const { schedule } = this.state;
    schedule[scheduleKey] = {value, invalid: false};
    this.setState({schedule});
  };

if I use validChar it would only allow the characters I want, but it would allow strings like 10:aaaM.

If I use validTime (this is the check I do for each render, to add a red border if invalid) in this context, I always returns false, because it excepts a full match: 10:0 is wrong, 10:00 PM is correct.

This is one way to do it. Set it to case insensitive.

^(0(?:[1-9]|$)|1(?:[0-2]|$))(?:(:)(?:([0-5])(?:([0-9])(?:(\\s)([ap]m?)?)?)?)?)?$

What you can get with this:

  • If group 5 length == 2 (am/pm) the entire time is finished.
  • Group 1 contains the partial or full valid data.
  • Group 2 contains the hours.
  • Group 3 and 4 contain the minute digits (join together).
  • Group 5 contains the am/pm.

There are 2 ways to use this regex.

  1. As a test for validity. If it does not match, put a red box around the
    edit box and let the user figure out the mistake.
  2. As a self correcting match:
    • Take off the last $ in the regex, allowing a partial match.
    • After every match, write back the group 1 (partial) to the edit box
      thus not allowing invalid entries.
      Wait for a submit button, then validate the entire string (start to finish).

Formatted / explained :

 ^                             # BOS
 (                             # (1 start)
      # Hours
      (                             # (2 start)
           0 
           (?: [1-9] | $ )
        |  1 
           (?: [0-2] | $ )
      )                             # (2 end)


      # Minutes
      (?:
           :                             # ':'
           (?:

                ( [0-5] )                     # (3), Min,digit 1
                (?:
                     ( [0-9] )                     # (4), Min,digit 2
                     (?:
                          \s                            # space
                          (                             # (5 start), AM / PM
                               [ap] m?
                          )?                            # (5 end)
                     )?
                )?

           )?
      )?
 )                             # (1 end)
 $                             # EOS

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM