I am trying to validate, with a RegEx, a user input to a date/time field in the following format: yyyy-mm-dd HH:mm. Since a user would type this one character at a time, the RegEx also needs to allow for all the substrings (e.g., yyyy-mm, yyyy-mm-dd H, etc.).
For example, the following date 2022-01-29 11:59 or any substring of it, such as (empty string), 202, 2022-01-, 2022-01-29, etc. should match.
Strings like 2022-13, 222- or 2024-01-01 23:111 should not match.
I am trying something like,
[0-9]{4}?-?(0[1-9]|1[0-2])-?(0[1-9]|[1-2][0-9]|3[0-1])? ?(2[0-3]|[01][0-9])?:?[0-5]?[0-9]?$
making every character optional, but it does not work since it can just skip parts of the string, e.g. 2022-29 returns match...
CodePudding user response:
It becomes a bit convoluted if you want to match number ranges properly as you type. Here is a regex solution with test cases that has many nested groups (to allow partial input) and validates the ranges of month, day, hours, and minutes:
const regex = /^([0-9]{0,3}|[0-9]{4}(-([01]|(0[1-9]|1[0-2])(-([0-3]|(0[1-9]|[12][0-9]|3[01])( ([0-2]|([0-1][0-9]|2[0-3])(:([0-5]|([0-4][0-9]|5[0-9]))?)?)?)?)?)?)?)?)$/;
[
'',
'2',
'20',
'202',
'2022',
'2022-',
'2022-0',
'2022-01',
'2022-01-',
'2022-01-2',
'2022-01-29',
'2022-01-29 ',
'2022-01-29 1',
'2022-01-29 11',
'2022-01-29 11:',
'2022-01-29 11:5',
'2022-01-29 11:59',
'202-01',
'2022-1-1',
'2022-13',
'2022-01-32',
'2024-01-01 24',
'2024-01-01 01:60',
'2024-01-01 23:111'
].forEach(str => console.log(str, '=>', regex.test(str)));
Output:
=> true
2 => true
20 => true
202 => true
2022 => true
2022- => true
2022-0 => true
2022-01 => true
2022-01- => true
2022-01-2 => true
2022-01-29 => true
2022-01-29 => true
2022-01-29 1 => true
2022-01-29 11 => true
2022-01-29 11: => true
2022-01-29 11:5 => true
2022-01-29 11:59 => true
202-01 => false
2022-1-1 => false
2022-13 => false
2022-01-32 => false
2024-01-01 24 => false
2024-01-01 01:60 => false
2024-01-01 23:111 => false
Hierarchy of regex:
^(-- start of string & group[0-9]{0,3}-- 0 to 3 digits for partial year
|-- logical or[0-9]{4}--(----- dash(--[01]-- one digit of month
|-- logical or(0[1-9]|1[0-2])-- two digits of month(----- dash(--[0-3]-- one digit of day
|-- logical or(0[1-9]|[12][0-9]|3[01])-- two digits of day(---- space(--[0-2]-- one digit of hours
|-- logical or([0-1][0-9]|2[0-3])-- two digits of hours(--:-- colon(--[0-5]-- one digit of minutes
|-- logical or([0-4][0-9]|5[0-9])-- two digits of minutes
)?--
)?--
)?--
)?--
)?--
)?--
)?--
)?--
)$-- end of string and group
Learn more about regex: https://twiki.org/cgi-bin/view/Codev/TWikiPresentation2018x10x14Regex
