Regular Expression for Date or Datetime Validation

Posted by Mr PHP on

This Regular Expression will verify if a date is a valid YYYY-MM-DD with an optional HH:MM:SS. It checks to see if the day is a valid day in the given month with the consideration of leap years.

I have created this regex several years ago and now I want to share it with the world. It is not 100% documented however I have posted output from RegexBuddy’s document function.

<?php
if (preg_match('/\\A(?:^((\\d{2}(([02468][048])|([13579][26]))[\\-\\/\\s]?((((0?[13578])|(1[02]))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(3[01])))|(((0?[469])|(11))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(30)))|(0?2[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])))))|(\\d{2}(([02468][1235679])|([13579][01345789]))[\\-\\/\\s]?((((0?[13578])|(1[02]))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(3[01])))|(((0?[469])|(11))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(30)))|(0?2[\\-\\/\\s]?((0?[1-9])|(1[0-9])|(2[0-8]))))))(\\s(((0?[0-9])|(1[0-9])|(2[0-3]))\\:([0-5][0-9])((\\s)|(\\:([0-5][0-9])))?))?$)\\z/', $date)) {
	// date is valid
} else {
	// date is invalid
}
// ^((\d{2}(([02468][048])|([13579][26]))[\-\/\s]?((((0?[13578])|(1[02]))[\-\/\s]?((0?[1-9])|([1-2][0-9])|(3[01])))|(((0?[469])|(11))[\-\/\s]?((0?[1-9])|([1-2][0-9])|(30)))|(0?2[\-\/\s]?((0?[1-9])|([1-2][0-9])))))|(\d{2}(([02468][1235679])|([13579][01345789]))[\-\/\s]?((((0?[13578])|(1[02]))[\-\/\s]?((0?[1-9])|([1-2][0-9])|(3[01])))|(((0?[469])|(11))[\-\/\s]?((0?[1-9])|([1-2][0-9])|(30)))|(0?2[\-\/\s]?((0?[1-9])|(1[0-9])|(2[0-8]))))))(\s(((0?[0-9])|(1[0-9])|(2[0-3]))\:([0-5][0-9])((\s)|(\:([0-5][0-9])))?))?$
// 
// Assert position at the start of the string «^»
// Match the regular expression below and capture its match into backreference number 1 «((\d{2}(([02468][048])|([13579][26]))[\-\/\s]?((((0?[13578])|(1[02]))[\-\/\s]?((0?[1-9])|([1-2][0-9])|(3[01])))|(((0?[469])|(11))[\-\/\s]?((0?[1-9])|([1-2][0-9])|(30)))|(0?2[\-\/\s]?((0?[1-9])|([1-2][0-9])))))|(\d{2}(([02468][1235679])|([13579][01345789]))[\-\/\s]?((((0?[13578])|(1[02]))[\-\/\s]?((0?[1-9])|([1-2][0-9])|(3[01])))|(((0?[469])|(11))[\-\/\s]?((0?[1-9])|([1-2][0-9])|(30)))|(0?2[\-\/\s]?((0?[1-9])|(1[0-9])|(2[0-8]))))))»
//    Match either the regular expression below (attempting the next alternative only if this one fails) «(\d{2}(([02468][048])|([13579][26]))[\-\/\s]?((((0?[13578])|(1[02]))[\-\/\s]?((0?[1-9])|([1-2][0-9])|(3[01])))|(((0?[469])|(11))[\-\/\s]?((0?[1-9])|([1-2][0-9])|(30)))|(0?2[\-\/\s]?((0?[1-9])|([1-2][0-9])))))»
//       Match the regular expression below and capture its match into backreference number 2 «(\d{2}(([02468][048])|([13579][26]))[\-\/\s]?((((0?[13578])|(1[02]))[\-\/\s]?((0?[1-9])|([1-2][0-9])|(3[01])))|(((0?[469])|(11))[\-\/\s]?((0?[1-9])|([1-2][0-9])|(30)))|(0?2[\-\/\s]?((0?[1-9])|([1-2][0-9])))))»
//          Match a single digit 0..9 «\d{2}»
//             Exactly 2 times «{2}»
//          Match the regular expression below and capture its match into backreference number 3 «(([02468][048])|([13579][26]))»
//             Match either the regular expression below (attempting the next alternative only if this one fails) «([02468][048])»
//                Match the regular expression below and capture its match into backreference number 4 «([02468][048])»
//                   Match a single character present in the list "02468" «[02468]»
//                   Match a single character present in the list "048" «[048]»
//             Or match regular expression number 2 below (the entire group fails if this one fails to match) «([13579][26])»
//                Match the regular expression below and capture its match into backreference number 5 «([13579][26])»
//                   Match a single character present in the list "13579" «[13579]»
//                   Match a single character present in the list "26" «[26]»
//          Match a single character present in the list below «[\-\/\s]?»
//             Between zero and one times, as many times as possible, giving back as needed (greedy) «?»
//             A - character «\-»
//             A / character «\/»
//             Match a single character that is a "whitespace character" (spaces, tabs, line breaks, etc.) «\s»
//          Match the regular expression below and capture its match into backreference number 6 «((((0?[13578])|(1[02]))[\-\/\s]?((0?[1-9])|([1-2][0-9])|(3[01])))|(((0?[469])|(11))[\-\/\s]?((0?[1-9])|([1-2][0-9])|(30)))|(0?2[\-\/\s]?((0?[1-9])|([1-2][0-9]))))»
//             Match either the regular expression below (attempting the next alternative only if this one fails) «(((0?[13578])|(1[02]))[\-\/\s]?((0?[1-9])|([1-2][0-9])|(3[01])))»
//                Match the regular expression below and capture its match into backreference number 7 «(((0?[13578])|(1[02]))[\-\/\s]?((0?[1-9])|([1-2][0-9])|(3[01])))»
//                   Match the regular expression below and capture its match into backreference number 8 «((0?[13578])|(1[02]))»
//                      Match either the regular expression below (attempting the next alternative only if this one fails) «(0?[13578])»
//                         Match the regular expression below and capture its match into backreference number 9 «(0?[13578])»
//                            Match the character "0" literally «0?»
//                               Between zero and one times, as many times as possible, giving back as needed (greedy) «?»
//                            Match a single character present in the list "13578" «[13578]»
//                      Or match regular expression number 2 below (the entire group fails if this one fails to match) «(1[02])»
//                         Match the regular expression below and capture its match into backreference number 10 «(1[02])»
//                            Match the character "1" literally «1»
//                            Match a single character present in the list "02" «[02]»
//                   Match a single character present in the list below «[\-\/\s]?»
//                      Between zero and one times, as many times as possible, giving back as needed (greedy) «?»
//                      A - character «\-»
//                      A / character «\/»
//                      Match a single character that is a "whitespace character" (spaces, tabs, line breaks, etc.) «\s»
//                   Match the regular expression below and capture its match into backreference number 11 «((0?[1-9])|([1-2][0-9])|(3[01]))»
//                      Match either the regular expression below (attempting the next alternative only if this one fails) «(0?[1-9])»
//                         Match the regular expression below and capture its match into backreference number 12 «(0?[1-9])»
//                            Match the character "0" literally «0?»
//                               Between zero and one times, as many times as possible, giving back as needed (greedy) «?»
//                            Match a single character in the range between "1" and "9" «[1-9]»
//                      Or match regular expression number 2 below (attempting the next alternative only if this one fails) «([1-2][0-9])»
//                         Match the regular expression below and capture its match into backreference number 13 «([1-2][0-9])»
//                            Match a single character in the range between "1" and "2" «[1-2]»
//                            Match a single character in the range between "0" and "9" «[0-9]»
//                      Or match regular expression number 3 below (the entire group fails if this one fails to match) «(3[01])»
//                         Match the regular expression below and capture its match into backreference number 14 «(3[01])»
//                            Match the character "3" literally «3»
//                            Match a single character present in the list "01" «[01]»
//             Or match regular expression number 2 below (attempting the next alternative only if this one fails) «(((0?[469])|(11))[\-\/\s]?((0?[1-9])|([1-2][0-9])|(30)))»
//                Match the regular expression below and capture its match into backreference number 15 «(((0?[469])|(11))[\-\/\s]?((0?[1-9])|([1-2][0-9])|(30)))»
//                   Match the regular expression below and capture its match into backreference number 16 «((0?[469])|(11))»
//                      Match either the regular expression below (attempting the next alternative only if this one fails) «(0?[469])»
//                         Match the regular expression below and capture its match into backreference number 17 «(0?[469])»
//                            Match the character "0" literally «0?»
//                               Between zero and one times, as many times as possible, giving back as needed (greedy) «?»
//                            Match a single character present in the list "469" «[469]»
//                      Or match regular expression number 2 below (the entire group fails if this one fails to match) «(11)»
//                         Match the regular expression below and capture its match into backreference number 18 «(11)»
//                            Match the characters "11" literally «11»
//                   Match a single character present in the list below «[\-\/\s]?»
//                      Between zero and one times, as many times as possible, giving back as needed (greedy) «?»
//                      A - character «\-»
//                      A / character «\/»
//                      Match a single character that is a "whitespace character" (spaces, tabs, line breaks, etc.) «\s»
//                   Match the regular expression below and capture its match into backreference number 19 «((0?[1-9])|([1-2][0-9])|(30))»
//                      Match either the regular expression below (attempting the next alternative only if this one fails) «(0?[1-9])»
//                         Match the regular expression below and capture its match into backreference number 20 «(0?[1-9])»
//                            Match the character "0" literally «0?»
//                               Between zero and one times, as many times as possible, giving back as needed (greedy) «?»
//                            Match a single character in the range between "1" and "9" «[1-9]»
//                      Or match regular expression number 2 below (attempting the next alternative only if this one fails) «([1-2][0-9])»
//                         Match the regular expression below and capture its match into backreference number 21 «([1-2][0-9])»
//                            Match a single character in the range between "1" and "2" «[1-2]»
//                            Match a single character in the range between "0" and "9" «[0-9]»
//                      Or match regular expression number 3 below (the entire group fails if this one fails to match) «(30)»
//                         Match the regular expression below and capture its match into backreference number 22 «(30)»
//                            Match the characters "30" literally «30»
//             Or match regular expression number 3 below (the entire group fails if this one fails to match) «(0?2[\-\/\s]?((0?[1-9])|([1-2][0-9])))»
//                Match the regular expression below and capture its match into backreference number 23 «(0?2[\-\/\s]?((0?[1-9])|([1-2][0-9])))»
//                   Match the character "0" literally «0?»
//                      Between zero and one times, as many times as possible, giving back as needed (greedy) «?»
//                   Match the character "2" literally «2»
//                   Match a single character present in the list below «[\-\/\s]?»
//                      Between zero and one times, as many times as possible, giving back as needed (greedy) «?»
//                      A - character «\-»
//                      A / character «\/»
//                      Match a single character that is a "whitespace character" (spaces, tabs, line breaks, etc.) «\s»
//                   Match the regular expression below and capture its match into backreference number 24 «((0?[1-9])|([1-2][0-9]))»
//                      Match either the regular expression below (attempting the next alternative only if this one fails) «(0?[1-9])»
//                         Match the regular expression below and capture its match into backreference number 25 «(0?[1-9])»
//                            Match the character "0" literally «0?»
//                               Between zero and one times, as many times as possible, giving back as needed (greedy) «?»
//                            Match a single character in the range between "1" and "9" «[1-9]»
//                      Or match regular expression number 2 below (the entire group fails if this one fails to match) «([1-2][0-9])»
//                         Match the regular expression below and capture its match into backreference number 26 «([1-2][0-9])»
//                            Match a single character in the range between "1" and "2" «[1-2]»
//                            Match a single character in the range between "0" and "9" «[0-9]»
//    Or match regular expression number 2 below (the entire group fails if this one fails to match) «(\d{2}(([02468][1235679])|([13579][01345789]))[\-\/\s]?((((0?[13578])|(1[02]))[\-\/\s]?((0?[1-9])|([1-2][0-9])|(3[01])))|(((0?[469])|(11))[\-\/\s]?((0?[1-9])|([1-2][0-9])|(30)))|(0?2[\-\/\s]?((0?[1-9])|(1[0-9])|(2[0-8])))))»
//       Match the regular expression below and capture its match into backreference number 27 «(\d{2}(([02468][1235679])|([13579][01345789]))[\-\/\s]?((((0?[13578])|(1[02]))[\-\/\s]?((0?[1-9])|([1-2][0-9])|(3[01])))|(((0?[469])|(11))[\-\/\s]?((0?[1-9])|([1-2][0-9])|(30)))|(0?2[\-\/\s]?((0?[1-9])|(1[0-9])|(2[0-8])))))»
//          Match a single digit 0..9 «\d{2}»
//             Exactly 2 times «{2}»
//          Match the regular expression below and capture its match into backreference number 28 «(([02468][1235679])|([13579][01345789]))»
//             Match either the regular expression below (attempting the next alternative only if this one fails) «([02468][1235679])»
//                Match the regular expression below and capture its match into backreference number 29 «([02468][1235679])»
//                   Match a single character present in the list "02468" «[02468]»
//                   Match a single character present in the list "1235679" «[1235679]»
//             Or match regular expression number 2 below (the entire group fails if this one fails to match) «([13579][01345789])»
//                Match the regular expression below and capture its match into backreference number 30 «([13579][01345789])»
//                   Match a single character present in the list "13579" «[13579]»
//                   Match a single character present in the list "01345789" «[01345789]»
//          Match a single character present in the list below «[\-\/\s]?»
//             Between zero and one times, as many times as possible, giving back as needed (greedy) «?»
//             A - character «\-»
//             A / character «\/»
//             Match a single character that is a "whitespace character" (spaces, tabs, line breaks, etc.) «\s»
//          Match the regular expression below and capture its match into backreference number 31 «((((0?[13578])|(1[02]))[\-\/\s]?((0?[1-9])|([1-2][0-9])|(3[01])))|(((0?[469])|(11))[\-\/\s]?((0?[1-9])|([1-2][0-9])|(30)))|(0?2[\-\/\s]?((0?[1-9])|(1[0-9])|(2[0-8]))))»
//             Match either the regular expression below (attempting the next alternative only if this one fails) «(((0?[13578])|(1[02]))[\-\/\s]?((0?[1-9])|([1-2][0-9])|(3[01])))»
//                Match the regular expression below and capture its match into backreference number 32 «(((0?[13578])|(1[02]))[\-\/\s]?((0?[1-9])|([1-2][0-9])|(3[01])))»
//                   Match the regular expression below and capture its match into backreference number 33 «((0?[13578])|(1[02]))»
//                      Match either the regular expression below (attempting the next alternative only if this one fails) «(0?[13578])»
//                         Match the regular expression below and capture its match into backreference number 34 «(0?[13578])»
//                            Match the character "0" literally «0?»
//                               Between zero and one times, as many times as possible, giving back as needed (greedy) «?»
//                            Match a single character present in the list "13578" «[13578]»
//                      Or match regular expression number 2 below (the entire group fails if this one fails to match) «(1[02])»
//                         Match the regular expression below and capture its match into backreference number 35 «(1[02])»
//                            Match the character "1" literally «1»
//                            Match a single character present in the list "02" «[02]»
//                   Match a single character present in the list below «[\-\/\s]?»
//                      Between zero and one times, as many times as possible, giving back as needed (greedy) «?»
//                      A - character «\-»
//                      A / character «\/»
//                      Match a single character that is a "whitespace character" (spaces, tabs, line breaks, etc.) «\s»
//                   Match the regular expression below and capture its match into backreference number 36 «((0?[1-9])|([1-2][0-9])|(3[01]))»
//                      Match either the regular expression below (attempting the next alternative only if this one fails) «(0?[1-9])»
//                         Match the regular expression below and capture its match into backreference number 37 «(0?[1-9])»
//                            Match the character "0" literally «0?»
//                               Between zero and one times, as many times as possible, giving back as needed (greedy) «?»
//                            Match a single character in the range between "1" and "9" «[1-9]»
//                      Or match regular expression number 2 below (attempting the next alternative only if this one fails) «([1-2][0-9])»
//                         Match the regular expression below and capture its match into backreference number 38 «([1-2][0-9])»
//                            Match a single character in the range between "1" and "2" «[1-2]»
//                            Match a single character in the range between "0" and "9" «[0-9]»
//                      Or match regular expression number 3 below (the entire group fails if this one fails to match) «(3[01])»
//                         Match the regular expression below and capture its match into backreference number 39 «(3[01])»
//                            Match the character "3" literally «3»
//                            Match a single character present in the list "01" «[01]»
//             Or match regular expression number 2 below (attempting the next alternative only if this one fails) «(((0?[469])|(11))[\-\/\s]?((0?[1-9])|([1-2][0-9])|(30)))»
//                Match the regular expression below and capture its match into backreference number 40 «(((0?[469])|(11))[\-\/\s]?((0?[1-9])|([1-2][0-9])|(30)))»
//                   Match the regular expression below and capture its match into backreference number 41 «((0?[469])|(11))»
//                      Match either the regular expression below (attempting the next alternative only if this one fails) «(0?[469])»
//                         Match the regular expression below and capture its match into backreference number 42 «(0?[469])»
//                            Match the character "0" literally «0?»
//                               Between zero and one times, as many times as possible, giving back as needed (greedy) «?»
//                            Match a single character present in the list "469" «[469]»
//                      Or match regular expression number 2 below (the entire group fails if this one fails to match) «(11)»
//                         Match the regular expression below and capture its match into backreference number 43 «(11)»
//                            Match the characters "11" literally «11»
//                   Match a single character present in the list below «[\-\/\s]?»
//                      Between zero and one times, as many times as possible, giving back as needed (greedy) «?»
//                      A - character «\-»
//                      A / character «\/»
//                      Match a single character that is a "whitespace character" (spaces, tabs, line breaks, etc.) «\s»
//                   Match the regular expression below and capture its match into backreference number 44 «((0?[1-9])|([1-2][0-9])|(30))»
//                      Match either the regular expression below (attempting the next alternative only if this one fails) «(0?[1-9])»
//                         Match the regular expression below and capture its match into backreference number 45 «(0?[1-9])»
//                            Match the character "0" literally «0?»
//                               Between zero and one times, as many times as possible, giving back as needed (greedy) «?»
//                            Match a single character in the range between "1" and "9" «[1-9]»
//                      Or match regular expression number 2 below (attempting the next alternative only if this one fails) «([1-2][0-9])»
//                         Match the regular expression below and capture its match into backreference number 46 «([1-2][0-9])»
//                            Match a single character in the range between "1" and "2" «[1-2]»
//                            Match a single character in the range between "0" and "9" «[0-9]»
//                      Or match regular expression number 3 below (the entire group fails if this one fails to match) «(30)»
//                         Match the regular expression below and capture its match into backreference number 47 «(30)»
//                            Match the characters "30" literally «30»
//             Or match regular expression number 3 below (the entire group fails if this one fails to match) «(0?2[\-\/\s]?((0?[1-9])|(1[0-9])|(2[0-8])))»
//                Match the regular expression below and capture its match into backreference number 48 «(0?2[\-\/\s]?((0?[1-9])|(1[0-9])|(2[0-8])))»
//                   Match the character "0" literally «0?»
//                      Between zero and one times, as many times as possible, giving back as needed (greedy) «?»
//                   Match the character "2" literally «2»
//                   Match a single character present in the list below «[\-\/\s]?»
//                      Between zero and one times, as many times as possible, giving back as needed (greedy) «?»
//                      A - character «\-»
//                      A / character «\/»
//                      Match a single character that is a "whitespace character" (spaces, tabs, line breaks, etc.) «\s»
//                   Match the regular expression below and capture its match into backreference number 49 «((0?[1-9])|(1[0-9])|(2[0-8]))»
//                      Match either the regular expression below (attempting the next alternative only if this one fails) «(0?[1-9])»
//                         Match the regular expression below and capture its match into backreference number 50 «(0?[1-9])»
//                            Match the character "0" literally «0?»
//                               Between zero and one times, as many times as possible, giving back as needed (greedy) «?»
//                            Match a single character in the range between "1" and "9" «[1-9]»
//                      Or match regular expression number 2 below (attempting the next alternative only if this one fails) «(1[0-9])»
//                         Match the regular expression below and capture its match into backreference number 51 «(1[0-9])»
//                            Match the character "1" literally «1»
//                            Match a single character in the range between "0" and "9" «[0-9]»
//                      Or match regular expression number 3 below (the entire group fails if this one fails to match) «(2[0-8])»
//                         Match the regular expression below and capture its match into backreference number 52 «(2[0-8])»
//                            Match the character "2" literally «2»
//                            Match a single character in the range between "0" and "8" «[0-8]»
// Match the regular expression below and capture its match into backreference number 53 «(\s(((0?[0-9])|(1[0-9])|(2[0-3]))\:([0-5][0-9])((\s)|(\:([0-5][0-9])))?))?»
//    Between zero and one times, as many times as possible, giving back as needed (greedy) «?»
//    Match a single character that is a "whitespace character" (spaces, tabs, line breaks, etc.) «\s»
//    Match the regular expression below and capture its match into backreference number 54 «(((0?[0-9])|(1[0-9])|(2[0-3]))\:([0-5][0-9])((\s)|(\:([0-5][0-9])))?)»
//       Match the regular expression below and capture its match into backreference number 55 «((0?[0-9])|(1[0-9])|(2[0-3]))»
//          Match either the regular expression below (attempting the next alternative only if this one fails) «(0?[0-9])»
//             Match the regular expression below and capture its match into backreference number 56 «(0?[0-9])»
//                Match the character "0" literally «0?»
//                   Between zero and one times, as many times as possible, giving back as needed (greedy) «?»
//                Match a single character in the range between "0" and "9" «[0-9]»
//          Or match regular expression number 2 below (attempting the next alternative only if this one fails) «(1[0-9])»
//             Match the regular expression below and capture its match into backreference number 57 «(1[0-9])»
//                Match the character "1" literally «1»
//                Match a single character in the range between "0" and "9" «[0-9]»
//          Or match regular expression number 3 below (the entire group fails if this one fails to match) «(2[0-3])»
//             Match the regular expression below and capture its match into backreference number 58 «(2[0-3])»
//                Match the character "2" literally «2»
//                Match a single character in the range between "0" and "3" «[0-3]»
//       Match the character ":" literally «\:»
//       Match the regular expression below and capture its match into backreference number 59 «([0-5][0-9])»
//          Match a single character in the range between "0" and "5" «[0-5]»
//          Match a single character in the range between "0" and "9" «[0-9]»
//       Match the regular expression below and capture its match into backreference number 60 «((\s)|(\:([0-5][0-9])))?»
//          Between zero and one times, as many times as possible, giving back as needed (greedy) «?»
//          Match either the regular expression below (attempting the next alternative only if this one fails) «(\s)»
//             Match the regular expression below and capture its match into backreference number 61 «(\s)»
//                Match a single character that is a "whitespace character" (spaces, tabs, line breaks, etc.) «\s»
//          Or match regular expression number 2 below (the entire group fails if this one fails to match) «(\:([0-5][0-9]))»
//             Match the regular expression below and capture its match into backreference number 62 «(\:([0-5][0-9]))»
//                Match the character ":" literally «\:»
//                Match the regular expression below and capture its match into backreference number 63 «([0-5][0-9])»
//                   Match a single character in the range between "0" and "5" «[0-5]»
//                   Match a single character in the range between "0" and "9" «[0-9]»
// Assert position at the end of the string (or before the line break at the end of the string, if any) «$»

Tagged with : PHP, Regex


Comments