I\'m trying to check that dates entered by end users are in the YYYY-MM-DD. Regex has never been my strong point, I keep getting a false return value for the preg_match() I
I know that this is a old question. But I think I have a good solution.
$date = "2016-02-21";
$format = "Y-m-d";
if(date($format, strtotime($date)) == date($date)) {
echo "true";
} else {
echo "false";
}
You can try it. If you change the date to 21.02.2016 the echo is false. And if you change the format after that to d.m.Y the echo is true.
With this easy code you should be able to check which date-format is used without checking it by the regex.
Maybe there is a person who will test it on every case. But I think my idea is generally valid. For me it seems logical.
[If you use Symfony 4.1.2 try this][1]
$validDate = explode("-",$request->get('date'));
if (checkdate(filter_var($validDate[1],FILTER_SANITIZE_NUMBER_INT),filter_var($validDate[0],FILTER_SANITIZE_NUMBER_INT),filter_var($validDate[2],FILTER_SANITIZE_NUMBER_INT))){
$date = date_create(filter_var($request->get('date'),FILTER_SANITIZE_SPECIAL_CHARS));
}else{
return $this->redirectToRoute('YOUR_ROUTE');
}
It's probably better to use another mechanism for this.
The modern solution, with DateTime:
$dt = DateTime::createFromFormat("Y-m-d", $date);
return $dt !== false && !array_sum($dt::getLastErrors());
This validates the input too: $dt !== false
ensures that the date can be parsed with the specified format and the array_sum
trick is a terse way of ensuring that PHP did not do "month shifting" (e.g. consider that January 32 is February 1). See DateTime::getLastErrors() for more information.
Old-school solution with explode and checkdate:
list($y, $m, $d) = array_pad(explode('-', $date, 3), 3, 0);
return ctype_digit("$y$m$d") && checkdate($m, $d, $y);
This validates that the input is a valid date as well. You can do that with a regex of course, but it's going to be more fuss -- and February 29 cannot be validated with a regex at all.
The drawback of this approach is that you have to be very careful to reject all possible "bad" inputs while not emitting a notice under any circumstances. Here's how:
explode
is limited to return 3 tokens (so that if the input is "1-2-3-4", $d
will become "3-4")ctype_digit
is used to make sure that the input does not contain any non-numeric characters (apart from the dashes)array_pad
is used (with a default value that will cause checkdate
to fail) to make sure that enough elements are returned so that if the input is "1-2" list()
will not emit a noticeYou can use a preg_match with a checkdate php function
$date = "2012-10-05";
$split = array();
if (preg_match ("/^([0-9]{4})-([0-9]{2})-([0-9]{2})$/", $date, $split))
{
return checkdate($split[2], $split[3], $split[1]);
}
return false;
This should tell you if the format is valid and if the input date is valid.
$datein = '2012-11-0';
if(preg_match('/^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])$/', $datein)){
echo 'good';
}else{
echo 'no good';
}