php date validation
Solution 1
You could use checkdate. For example, something like this:
$test_date = '03/22/2010';
$test_arr = explode('/', $test_date);
if (checkdate($test_arr[0], $test_arr[1], $test_arr[2])) {
// valid date ...
}
A more paranoid approach, that doesn't blindly believe the input:
$test_date = '03/22/2010';
$test_arr = explode('/', $test_date);
if (count($test_arr) == 3) {
if (checkdate($test_arr[0], $test_arr[1], $test_arr[2])) {
// valid date ...
} else {
// problem with dates ...
}
} else {
// problem with input ...
}
Solution 2
You can use some methods of the DateTime
class, which might be handy; namely, DateTime::createFromFormat()
in conjunction with DateTime::getLastErrors()
.
$test_date = '03/22/2010';
$date = DateTime::createFromFormat('m/d/Y', $test_date);
$date_errors = DateTime::getLastErrors();
if ($date_errors['warning_count'] + $date_errors['error_count'] > 0) {
$errors[] = 'Some useful error message goes here.';
}
This even allows us to see what actually caused the date parsing warnings/errors (look at the warnings
and errors
arrays in $date_errors
).
Solution 3
Though checkdate
is good, this seems much concise function to validate and also you can give formats. [Source]
function validateDate($date, $format = 'Y-m-d H:i:s') {
$d = DateTime::createFromFormat($format, $date);
return $d && $d->format($format) == $date;
}
function was copied from this answer or php.net
The extra ->format()
is needed for cases where the date is invalid but createFromFormat
still manages to create a DateTime object. For example:
// Gives "2016-11-10 ..." because Thursday falls on Nov 10
DateTime::createFromFormat('D M j Y', 'Thu Nov 9 2016');
// false, Nov 9 is a Wednesday
validateDate('Thu Nov 9 2016', 'D M j Y');
Solution 4
Instead of the bulky DateTime object .. just use the core date() function
function isValidDate($date, $format= 'Y-m-d'){
return $date == date($format, strtotime($date));
}
Solution 5
Use it:
function validate_Date($mydate,$format = 'DD-MM-YYYY') {
if ($format == 'YYYY-MM-DD') list($year, $month, $day) = explode('-', $mydate);
if ($format == 'YYYY/MM/DD') list($year, $month, $day) = explode('/', $mydate);
if ($format == 'YYYY.MM.DD') list($year, $month, $day) = explode('.', $mydate);
if ($format == 'DD-MM-YYYY') list($day, $month, $year) = explode('-', $mydate);
if ($format == 'DD/MM/YYYY') list($day, $month, $year) = explode('/', $mydate);
if ($format == 'DD.MM.YYYY') list($day, $month, $year) = explode('.', $mydate);
if ($format == 'MM-DD-YYYY') list($month, $day, $year) = explode('-', $mydate);
if ($format == 'MM/DD/YYYY') list($month, $day, $year) = explode('/', $mydate);
if ($format == 'MM.DD.YYYY') list($month, $day, $year) = explode('.', $mydate);
if (is_numeric($year) && is_numeric($month) && is_numeric($day))
return checkdate($month,$day,$year);
return false;
}
Pablo Lopez
Updated on August 20, 2020Comments
-
Pablo Lopez over 3 years
Im trying to to set up a php date validation (MM/DD/YYYY) but I'm having issues. Here is a sample of what I got:
$date_regex = '%\A(0[1-9]|1[012])[- /.](0[1-9]|[12][0-9]|3[01])[- /.](19|20)\d\d\z%'; $test_date = '03/22/2010'; if (preg_match($date_regex, $test_date,$_POST['birthday']) ==true) { $errors[] = 'user name most have no spaces';`
-
Cody Caughlan over 11 yearsThis is the best solution as it also checks for invalid dates, e.g. Feb 29. A pure regex approach based on formatting would allow invalid dates.
-
Madara's Ghost over 11 years+1 for a regexless solution. Not all problems need a regex solution.
-
zerkms over 11 yearsregex solution also checked for a format, while this doesn't. If string
foobar
is passed - you'll get notices -
salathe over 11 yearsLet's come into the 21st century.
DateTime::createFromFormat()
andDateTime::getLastErrors()
. Thank me later. -
Sk446 over 11 years@salathe has the best approach. Nicolás should really update his answer as it's providing an old approach of doing this.
-
s3m3n about 11 yearsIt's worth to mention that you can check it straight with
DateTime::createFromFormat()
only, by checking if it's false, soif(DateTime::createFromFormat('m/d/Y', $test_date) === false) exit('bad date format');
-
salathe about 11 yearsOnly very crudely @s3m3n. For example, without checking for warnings, "44/33/2211" is a valid
m/d/Y
date (it is2nd Sep 2214
btw). -
s3m3n about 11 yearsYou are right, but in my case I'm only validating if moderator didn't make literal mistake in date format which is going directly to database instead of logical sense of given date. Someone else might need the same thing.
-
Nitsan Baleli almost 10 yearsDateTime::createFromFormat(PHP 5 >= 5.3.0)
-
o0'. almost 9 yearsThis is not always the best approach. If you receive the input already in separated values, but you don't know how exactly they are formatted (
M
vs.MM
,YYYY
vs.YY
), I thinkcheckdate
would be more flexible and accept anything that resembles a valid date. Additionaly, withDateTime
, if I write31
as the month it will be considered valid, and simply add2
years and set it to July (since31%12 = 7
). I really don't think this would be expected behaviour by many people… -
Gras Double over 8 yearsWhy/when is the extra verification
$d->format($format) == $date
needed? -
BillyTom over 8 yearsBut why would you want regex in the first place?
-
jjwdesign about 8 years@Gras Double - Validation. He's returning true/false, but ensuring that the DateTime object was created and that the formatted DateTime equals the function input $date.
-
Gras Double about 8 yearsSure, but a
return (bool) $d;
would do it. My question was, as the createFromFormat succeeded, in what scenario could the$d->format()
be different from the input? -
Gras Double about 8 yearsI have found this:
validateDate('Mon, 21-Jan-2041 15:24:52 GMT', DateTime::COOKIE);
. Returns false because the->format()
produces "Monday" instead of "Mon". Though, it would be better to return true, as the input is valid. I'm updating the answer. -
Gras Double about 8 yearsFound out a purpose for the
->format()
verification. Answer updated again. -
Gras Double about 8 years@ksimka Actually yes, see answer above.
-
Rich R about 8 yearsThe call to format will throw an exception if the date is invalid.
-
GordonM almost 7 yearsThis question has already had plenty of far superior answers, what's more it's years old. Your answer adds nothing. Please don't indulge in necromancing.
-
rolinger about 4 yearsEveryone, in multiple posts, keeps saying to use checkdate. But checkdate fails if the year is : 2, 20, 202, 2020 or even 20201 - it returns true every time.
-
Andrew Rump over 3 yearsWhy not just test if strtotime() === false?
-
Nicolás Ozimica over 3 years@rolinger Why should checkdate fail with such years??? First: are they invalid years? Second: the documentation for
checkdate
explicitly states that: "The year is between 1 and 32767 inclusive."