1

I have a regular expression that I need to add 24-hour time format to:

^(((((0[13578])|([13578])|(1[02]))[\-\/\s]?((0[1-9])|([1-9])|([1-2][0-9])|(3[01])))|((([469])|(11))[\-\/\s]?((0[1-9])|([1-9])|([1-2][0-9])|(30)))|((02|2)[\-\/\s]?((0[1-9])|([1-9])|([1-2][0-9]))))[\-\/\s]?\d{4})(\s(((0[1-9])|([1-9])|(1[0-2]))\:([0-5][0-9])((\s)|(\:([0-5][0-9])\s))([AM|PM|am|pm]{2,2})))?$

How would I go about adding 24 hour time format.

HaveNoDisplayName
  • 8,291
  • 106
  • 37
  • 47
llerdal
  • 377
  • 1
  • 4
  • 16
  • Can you give an example of how you want the matched strings to look like? – ndnenkov Aug 17 '15 at 15:53
  • @ndn ex. 12/30/2013 20:14 but not except 12/30/2013 24:00. – llerdal Aug 17 '15 at 15:58
  • 3
    Dates with regex are a big no-no. Accounting for leap years is just terrible. – ndnenkov Aug 17 '15 at 16:00
  • You might get some clues here : http://stackoverflow.com/questions/24375711/mm-dd-yyyy-hhmmss-am-pm-date-validation-regular-expression-in-javascript – PaulF Aug 17 '15 at 16:06
  • Don't do full date validation with regex. Basic sanity checks that the month is between 1 and 12, and the day between 1 and 31, and the year between 1800 and 2100, are reasonable. Real date validation should involve an attempt to convert a value to a date through a programming language. – ErikE Aug 17 '15 at 17:57
  • When your regular expression looks like somebody barfed on your program, you should consider writing a small parser. It'll be easier to prove correct, and you're much more likely to understand it six months from now. – Jim Mischel Aug 17 '15 at 18:00
  • @JimMischel, I think you overestimate people's abilities. I already can't read mine. xd – ndnenkov Aug 17 '15 at 18:06
  • @ndn: I've been told before that I'm overly optimistic. – Jim Mischel Aug 17 '15 at 18:19

1 Answers1

5

TLDR: Don't freaking do it with regex!


The time part:
/(?:[01]\d|2[0-3]):[0-5]\d/

A basic attempt at the date part:

/(?:0[1-9]|1[0-2])\/(?:0[1-9]|[12]\d|3[01])\/\d{4,}/

A more advanced attempt at the date part (validates correctly, except for February):

/(?:(?:0[13578]|1[02])\/(?:0[1-9]|[12]\d|3[01])|(?:0[2469]|11)\/(?:0[1-9]|[12]\d|30))\/\d{4,}/

Going further, assuming each year is a leap one:

/(?:(?:0[13578]|1[02])\/(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)\/(?:0[1-9]|[12]\d|30)|02\/(?:0[1-9]|[12]\d))\/\d{4,}/

Divisibility by 4:

/\d*(?:[13579][26]|[02468][048])(?!\d)/

Not divisible by 100 or divisible by 400:

/\d*(?:(?!\d{2}00)|(?=(?:[13579][26]|[02468][048])00))\d{4}(?!\d)/

Is leap year:

/\d*(?:(?:(?!\d{2}00)(?=\d{2}(?:[13579][26]|[02468][048])))|(?=(?:[13579][26]|[02468][048])00))\d{4}(?!\d)/

Only valid February dates:

/02\/(?:0[1-9]|1\d|2[0-8]|29(?=\/\d*(?:(?:(?!\d{2}00)(?=\d{2}(?:[13579][26]|[02468][048])))|(?=(?:[13579][26]|[02468][048])00))\d{4}(?!\d)))\/\d{4,}/

A valid date:

/(?:(?:0[13578]|1[02])\/(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)\/(?:0[1-9]|[12]\d|30)|02\/(?:0[1-9]|1\d|2[0-8]|29(?=\/\d*(?:(?:(?!\d{2}00)(?=\d{2}(?:[13579][26]|[02468][048])))|(?=(?:[13579][26]|[02468][048])00))\d{4}(?!\d))))\/\d{4,}/


Now everything in one place!

Date and time:

/^(?:(?:0[13578]|1[02])\/(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)\/(?:0[1-9]|[12]\d|30)|02\/(?:0[1-9]|1\d|2[0-8]|29(?=\/\d*(?:(?:(?!\d{2}00)(?=\d{2}(?:[13579][26]|[02468][048])))|(?=(?:[13579][26]|[02468][048])00))\d{4}(?!\d))))\/\d{4,} (?:[01]\d|2[0-3]):[0-5]\d$/


Can this be simplified? Most definitely!

Will I do it? Hell no!

I think the message is clear - don't do it!

ndnenkov
  • 35,425
  • 9
  • 72
  • 104
  • Agree that lookaround is a far superior way to deal with leap years and month lengths than pure alternation. – ErikE Aug 17 '15 at 17:28
  • Please strengthen the recommendation to not do this with regex. Some explanation of why. Then a strong warning before the regex you do provide, that suggests it's full of errors, may not work, will be impossible to understand or maintain, and should only be used by pirate mice, AWOL sunbeams, and foolish developers. – ErikE Aug 17 '15 at 17:58
  • @ErikE, I think big bold text at the beginning and end is enough. It should be fairly obvious why using this is a bad idea. BTW, I dare you to try and break it! xd – ndnenkov Aug 17 '15 at 18:00
  • I don't think the bold text is enough. People go past warnings all the time. To get them to stop, you have to explain why. You can't make a horse drink, but you should lead him to water first instead of just wave broadly and say the water is over the mountain somewhere. – ErikE Aug 17 '15 at 18:02