I\'m obviously not using filter_var() correctly. I need to check that the user has entered a valid date, in the form \"dd/mm/yyyy\".
This simply returns whatever I p
$myregex = '~^\d{2}/\d{2}/\d{4}$~';
The regex matched because you just require that pattern anywhere in the string. What you want is only that pattern and nothing else. So add ^
and $
.
Note that this still doesn't mean the value is a valid date. 99/99/9999
will pass that test. I'd use:
if (!DateTime::createFromFormat('d/m/Y', $string))
Why using a heavy RegEx, while there is a native DateTime PHP-class?
$value = 'badbadbad';
try {
$datetime = new \DateTime($value);
$value = $datetime->format('Y-m-d');
} catch(\Exception $e) {
// Invalid date
}
Always returns the format you were expecting, if a valid datetime string was inserted.
Using regex to validate date is a bad idea .. Imagine 99/99/9999
can easily be seen as a valid date .. you should checkdate
bool checkdate ( int $month , int $day , int $year )
Simple Usage
$date = "01/02/0000";
$date = date_parse($date); // or date_parse_from_format("d/m/Y", $date);
if (checkdate($date['month'], $date['day'], $date['year'])) {
// Valid Date
}
The better solution is posted by @baba, but the code posted doesn't work fine in certain conditions.
For example if you try to validate this date "2019-12-313";
$date = date_parse("2019-12-313");
the function returns this array:
Array
(
[year] => 2019
[month] => 12
[day] => 31
[hour] =>
[minute] =>
[second] =>
[fraction] =>
[warning_count] => 0
[warnings] => Array
(
)
[error_count] => 1
[errors] => Array
(
[10] => Unexpected character
)
[is_localtime] =>
)
so, if you perform the command:
checkdate($date['month'], $date['day'], $date['year']);
checkdate will returns a true value because the value of $date['day']
is 31 instead of 313.
to avoid this case maybe you have to add a check to the value of $date['error_count']
the @baba example updated
$date = "2019-12-313";
$date = date_parse($date); // or date_parse_from_format("d/m/Y", $date);
if ($date['error_count'] == 0 && checkdate($date['month'], $date['day'], $date['year'])) {
// Valid Date
}
$myregex = "~^(19|20)\d\d[- /.](0[1-9]|1[012])[- /.](0[1-9]|[12][0-9]|3[01])$~";
print filter_var("bad 01/02/2012 bad",FILTER_VALIDATE_REGEXP,array("options"=>array("regexp"=> $myregex)));
You received a lot of answers that indicated the RegEx would allow for an answer of 99/99/9999. That can be solved by adding a little more to the RegEx. If you know you'll never have a date outside of the years 1900-2099... you can use a RegEx like this:
/^(0[1-9]|[12][0-9]|3[01])[/](0[1-9]|1[012])[/](19|20)\d\d$/
That will validate a date of this format: dd/mm/YYYY
Between: 01/01/1900 - 31/12/2099
If you need more years, just add them near the end. |21|22|23|24|25 (would extend it to the year 2599.)