Regular Expression to match a valid day in a date

后端 未结 10 1704
别那么骄傲
别那么骄傲 2020-12-11 01:45

I need help coming up with a regex to make sure the user enters a valid date The string will be in the format of mm/dd/yyyy

Here is what I have come up

相关标签:
10条回答
  • 2020-12-11 02:23
    use DateTime;
    

    Other solutions are fine, probably work, etc. Usually, you end up wanting to do a bit more, and then a bit more, and eventually you have some crazy code, and leap years, and why are you doing it yourself again?

    DateTime and its formatters are your solution. Use them! Sometimes they are a bit overkill, but often that works out for you down the road.

    my $dayFormat = new DateTime::Format::Strptime(pattern => '%d/%m/%Y');
    my $foo = $dayFormat->parse_datetime($myDateString);
    

    $foo is now a DateTime object. Enjoy.

    If your date string wasn't properly formatted, $foo will be "undef" and $dayFormat->errstr will tell you why.

    0 讨论(0)
  • 2020-12-11 02:25

    I have been working with this some time and the best regex I've came up with is the following:

    \b(0)?(?(1)[1-9]|(3)?(?(2)[01]|[12][0-9]))\b|\b[1-9]\b
    

    It will match the following numbers:

    1 01 10 15 20 25 30 31
    

    It does not match the following:

    32 40 50 90
    
    0 讨论(0)
  • 2020-12-11 02:27
    • As many have noted above, if we want to validate the date as a whole then a RegEx is a very poor choice.
    • But if we want to match a pattern of numbers, in this case from 01-31 then RegEx is fine so long as there is some backend logic that validates the date as a whole, if so desired.
    • I see the expected answer currently fails for 10, 20.

      • Test: gawk 'BEGIN{ for(i=0;i<=32;i++){ if (i ~ /^([0-2]?[1-9]|3[01])$/){print i " yes"}else {print i " no"} } }
      • This can be corrected as follows: ^([0-2]?[1-9]|3[01]|10|20)$

    So kindly consider the following solution...

    1. Identify the sets that need to be matched:

    • Days with prefix "0": {01,...,09},{10,...,31}
      • Sub-set {10,...,31} can be split into => {10,...,29},{30,31}
    • Without any prefix: {1,...,31} => {1,...,9},{10,...,31}

    2. Corresponding regular expressions for each sub-set:

    ---------------------------------
    Sub-Set     |  Regular-Expression
    ---------------------------------
    {01,...,09} | [0][1-9]
    {10,...,29} | [1-2][0-9]
    {30,31}     | 3[01]
    {1,...,9}   | [1-9]
    ---------------------------------
    

    Now we can group ([0][1-9]) and ([1-9]) together as ([0]?[1-9]). Where ? signifies 0 or 1 occurrences of the pattern/symbol. [UPDATE] - Thank you @MattFrear for pointing it out.

    So the resulting RegEx is: ^(([0]?[1-9])|([1-2][0-9])|(3[01]))$

    Tested here: http://regexr.com/?383k1 [UPDATE]

    0 讨论(0)
  • 2020-12-11 02:28
    ^(((((((0?[13578])|(1[02]))[\.\-/]?((0?[1-9])|([12]\d)|(3[01])))|(((0?[469])|(11))[\.\-/]?((0?[1-9])|([12]\d)|(30)))|((0?2)[\.\-/]?((0?[1-9])|(1\d)|(2[0-8]))))[\.\-/]?(((19)|(20))?([\d][\d]))))|((0?2)[\.\-/]?(29)[\.\-/]?(((19)|(20))?(([02468][048])|([13579][26])))))$
    

    From Expressions in category: Dates and Times

    Validates the correct number of days in a month, looks like it even handles leap years.

    You can of course change [\.\-/] with / to only allow slashes.

    0 讨论(0)
提交回复
热议问题