Regular Expression: match hh:mm, hh.mm or h

Slevin picture Slevin · Jul 10, 2012 · Viewed 8.2k times · Source

I'm looking for a regular expression to match different time formats (for a time tracking web-app) in javascript. The user can insert times with one of the following formats:

h
hh:mm
hh.mm

I can easily create a regular expression to match hh:mm and hh.mm, but i can't get the single hour format working.

This is my current regex: ([0-2][0-9])(.|:)([0-5][0-9])

Allowed character: 0-9, . and :. If the user types any other character, the validation should fail.

Does anyone have any suggestions?

Edit

following formats should work to:

h:mm (3:30)

solution: http://regexr.com?31gc3

Answer

Brian Nickel picture Brian Nickel · Jul 10, 2012

You can make a block optional by placing it in ( ... )? This is equivalent to ( ... ){0,1} which allows zero or one references.

Your expression becomes:

/([0-2][0-9])((.|:)([0-5][0-9]))?/

This matches 12, 12:30 and 12.30. It won't match 5, 5:30, or 5.30. Enabling a single digit hour input can be done by making the first digit optional:

/([0-2]?[0-9])((.|:)([0-5][0-9]))?/

If you're using .match, you will notice you have 5 results:

["12:30", "12", ":30", ":", "30"]

You can reduce that to 3 by eliminating unnecessary matching when you turn ( ... ) into (?: ... )

/([0-2]?[0-9])(?:(?:.|:)([0-5][0-9]))?/

This gives you:

["12:30", "12", "30"]

Update

Based on your update, you want to match boundaries. There are a couple ways to do this.

  1. Starting with ^ will tie the front of your expression to the beginning of each line/string.
  2. Ending with $ will tie the end of your expression to the end of the string.
  3. Starting or ending with \b will mandate that the edge is against a "boundary".

Putting that all together:

If you just want to match lines that contain nothing but the date you can use:

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

This will not catch "hello 1.30" or "1.30 hello".

If you want to match lines that start with a date you could use:

/^([0-2]?[0-9])(?:(?:.|:)([0-5][0-9]))?/

But this will match "1.30000".

your best bet if you're looking for dates at the start of lines is:

/^([0-2]?[0-9])(?:(?:.|:)([0-5][0-9]))?\b/

As it will match "1.30 test" but not "1.300000". Unfortunately, it will also match "1.30.30", but that is a limitation of JavaScript's RegExp processor.

If you're looking for times inside strings, this becomes:

/\b([0-2]?[0-9])(?:(?:.|:)([0-5][0-9]))?\b/

It matches "test 1.30 test" with the unfortunate case of matching stuff like ".10.10.10".