tofat
asked on
dd/mm/yyyy php date validation
I found some cool code that is meant to validate the date in dd/mm/yyyy format and also check that the day of the month actually exists i.e.: you can't type in 31/02/2016. But even if I put in a perfectly valid date it still throws the error that the date is invalid for some reason?
function isDate($string) {
$matches = array();
$pattern = '/^([0-9]{1,2})\\/([0-9]{1,2})\\/([0-9]{4})$/';
if (!preg_match($pattern, $string, $matches)) return false;
if (!checkdate($matches[2], $matches[1], $matches[3])) return false;
return true;
}
if (!isDate($date)) {
$error .= "invalid date.<br>";
}
ASKER
Great link, thanks for that. I changed it to:
#^([0-9]{1,2})\\#([0-9]{1, 2})\\#([0- 9]{4})$#
and it does't throw any errors any more. However, when I put in a test string of 30/06/2016 it says,
"Your pattern does not match the subject string."
I also tried changing it to :
#^([0-9]{2})\\#([0-9]{2})\ \#([0-9]{4 })$#
because it said that 1,2 was greedy. But that didn't work either.
#^([0-9]{1,2})\\#([0-9]{1,
and it does't throw any errors any more. However, when I put in a test string of 30/06/2016 it says,
"Your pattern does not match the subject string."
I also tried changing it to :
#^([0-9]{2})\\#([0-9]{2})\
because it said that 1,2 was greedy. But that didn't work either.
Tofat, you have to change only delimiters not all slashes :)
#^([0-9]{1,2})\\/([0-9]{1, 2})\\/([0- 9]{4})$#
#^([0-9]{1,2})\\/([0-9]{1,
Date / Time processing in PHP is fairly well documented here. The PHP built-in functions and classes have certain rules that work perfectly. No need for regular expressions at all! However if you want to use dd/mm/yyyy you would want to translate the slashes into dashes. Details of the allowable formats are here:
http://php.net/manual/en/datetime.formats.date.php
Translation process:
Procedural Details
https://www.experts-exchange.com/articles/201/Handling-Date-and-Time-in-PHP-and-MySQL-Procedural-Version.html
Object-Oriented Details
https://www.experts-exchange.com/articles/20920/Handling-Time-and-Date-in-PHP-and-MySQL-OOP-Version.html
http://php.net/manual/en/datetime.formats.date.php
Translation process:
$ddmmyyyy = str_replace('/', '-', $ddmmyyyy);
Procedural Details
https://www.experts-exchange.com/articles/201/Handling-Date-and-Time-in-PHP-and-MySQL-Procedural-Version.html
Object-Oriented Details
https://www.experts-exchange.com/articles/20920/Handling-Time-and-Date-in-PHP-and-MySQL-OOP-Version.html
$pattern = '#^([0-9]{1,2})\\/([0-9]{1,2})\\/([0 -9]{4})$#' ;
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
For a complete regex, see here: http://stackoverflow.com/questions/15491894/regex-to-validate-date-format-dd-mm-yyyy and it fails for php anyway.
I wouldn't want to put this into my code, then later come back and say - "ah yes". You would rather come back to this code and say "huh?" That feeling also can't really be fixed by a comment. If an error happens and you'd need to fix it, then what?
The short regex is good for prefiltering any strings not even close to a good date format, so you don't try to convert 'hello' into a date. But that's all it may provide.
Bye, Olaf.
I wouldn't want to put this into my code, then later come back and say - "ah yes". You would rather come back to this code and say "huh?" That feeling also can't really be fixed by a comment. If an error happens and you'd need to fix it, then what?
The short regex is good for prefiltering any strings not even close to a good date format, so you don't try to convert 'hello' into a date. But that's all it may provide.
Bye, Olaf.
@Olaf: the correct date check is done through the checkdate() function calles at line 5. Good point insted for the double escaping: I don't know how I could miss that which result even from here: https://www.regex101.com/r/kN2yE9/1
So, summarizing, the correct regex is the one pointed out by Olaf: /^[0-9]{1,2}\/[0-9]{1,2}\/ [0-9]{1,4} $/ Once matched, checkdate() should work as expected :)
So, summarizing, the correct regex is the one pointed out by Olaf: /^[0-9]{1,2}\/[0-9]{1,2}\/
I see, the preg_match is just extracing the day, month, and year.
Still Ray has the simplest solution, you simply try to insert into a date or datetime (after replacing slashes with dashes) amd handle problems. It may not be the taste of some to not avoid sql errors in advance rather than handle them, many other things but the date may be wrong and so prechecking can be easier.
Bye, Olaf.
Still Ray has the simplest solution, you simply try to insert into a date or datetime (after replacing slashes with dashes) amd handle problems. It may not be the taste of some to not avoid sql errors in advance rather than handle them, many other things but the date may be wrong and so prechecking can be easier.
Bye, Olaf.
ASKER
Thank you all for your comments. I like Ray's post that says I don't have to use regular expressions but I don't know how to implement that. I have quickly put this together but wondered 2 things, how can I change the format from dd/mm/yy to dd/mm/yyyy and how would i validate the form to make it check that the format dd/mm/yyyy is correct?
<html>
<head>
<?php
$pretty_date = date('d/m/y');
$mydate = ($_POST['mydate']);
?>
</head>
<body>
<form method="post" action="<?php echo htmlspecialchars($_SERVER[" PHP_SELF "]);?>">
<input type="text" name="mydate">
<input type="submit" name="submit" value="Submit"> Your date is:<?php echo $mydate; ?>
</form>
</body>
</html>
To format the date for a 4 digit yesr just use Y instead of y
$pretty_date = date('d/m/Y');
But to check if the user used the requested format I think you have to go back to a regex...
ASKER
Haha, I was just thinking that. But then I don't understand Ray's post where he suggests I don't need to use regex. Unless I misunderstood?
Otherwise you could replace your text input with 2 select for days and months and a text input for the year checking if is 4 characters long
ASKER
By the way, I changed the regex to this and it still doesn't work
function isDate($string) {
$matches = array();
$pattern = '^([0-9]{1,2})\/([0-9]{1,2})\/([0-9]{4})$';
if (!preg_match($pattern, $string, $matches)) return false;
if (!checkdate($matches[2], $matches[1], $matches[3])) return false;
return true;
}
if (!isDate($date)) {
$error .= "invalid date.<br>";
}
You missed the delimiters:
$pattern = '/^([0-9]{1,2})\/([0-9]{1,2})\/([0-9]{4})$/';
<?php
/**
* https://www.experts-exchange.com/questions/28955059/dd-mm-yyyy-php-date-validation.html#a41686219
*/
error_reporting(E_ALL);
// WRONG: DATE IS JANUARY 7, 2016 IF FORMATTED AS DD/MM/YYYY
$ddmmyyyy = '07/01/2016';
echo PHP_EOL . date('r', strtotime($ddmmyyyy));
// RIGHT
$ddmmyyyy = str_replace('/', '-', $ddmmyyyy);
echo PHP_EOL . date('r', strtotime($ddmmyyyy));
Outputs:
Fri, 01 Jul 2016 00:00:00 -0500
Thu, 07 Jan 2016 00:00:00 -0600
ASKER
It is still saying invalid date:
function isDate($string) {
$matches = array();
$pattern = '/^([0-9]{1,2})\/([0-9]{1,2})\/([0-9]{4})$/';
if (!preg_match($pattern, $string, $matches)) return false;
if (!checkdate($matches[2], $matches[1], $matches[3])) return false;
return true;
}
if (!isDate($date)) {
$error .= "invalid date.<br>";
}
What works with strtotime()?
https://iconoun.com/demo/strtotime.php
https://iconoun.com/demo/strtotime.php
<?php // demo/strtotime.php
/**
* Show what works with strtotime()
*
* http://php.net/manual/en/function.strtotime.php
* http://php.net/manual/en/function.date.php
* http://php.net/manual/en/datetime.formats.php
* http://php.net/manual/en/datetime.formats.relative.php
*
*/
error_reporting(E_ALL);
// RESPONSE STRING HERE
$obuff = NULL;
// MAN PAGE http://php.net/manual/en/function.date-default-timezone-set.php
date_default_timezone_set('America/Chicago');
// IF WE HAVE INPUT FROM THE URL QUERY STRING
if (!empty($_GET["s"]))
{
$urlink = '<a href="' . $_SERVER['REQUEST_URI'] . '">' . $_GET['s'] . '</a>';
// COLLECT THE OUTPUT BUFFER
ob_start();
// USE strtotime() FUNCTION TO MAKE A TIMESTAMP
$unix_timestamp = strtotime($_GET["s"]);
// TEST FOR SUCCESS OR FAILURE
if ($unix_timestamp === FALSE)
{
echo "<strong>HONK!</strong><br /> <u>$urlink</u> NOT USEFUL WITH strtotime() <br/><br/><br/><br/>";
}
// ON SUCCESS, PRINT THE RESULTS
else
{
echo "<strong>BINGO</strong><br /> <strong><u>$urlink</u></strong> WORKS WITH strtotime() <br/>";
echo "THE INTEGER TIMESTAMP VALUE IS ";
echo number_format($unix_timestamp) . "<br />";
// FORMAT ISO AND HUMAN-READABLE DATES
$y = date('c', $unix_timestamp);
echo "THE ISO8601 DATETIME STRING IS $y<br />";
$z = date('l, \t\h\e jS \o\f F Y g:i:s A', $unix_timestamp);
echo "THE TEXTUAL DATE IS $z<br />";
}
// RECOVER THE RESPONSE FROM THE OUTPUT BUFFER
$obuff = ob_get_clean();
} // END OF PROCESSING INPUT
$tzone = date_default_timezone_get();
$phpvs = phpversion();
// CREATE THE HTML FORM USING HEREDOC NOTATION
$htmls = <<<HTMLS
<!DOCTYPE html>
<html dir="ltr" lang="en-US">
<head>
<meta charset="utf-8" />
<title>PHP strtotime()</title>
</head>
<body onload="document.f.s.focus()">
$obuff
<form name="f" method="get">
<br />TO TEST A STRING FOR A VALID DATE/TIME, TYPE IT HERE:<input name="s" />
<input type="submit" value="GO" />
</form>
<br/><strong>Note: Your local time may vary. This server is in $tzone</strong>
<br/>Current PHP version is $phpvs
<br/>TRY TESTING SOME OF THESE STRINGS (CLICK THE LINK, OR COPY AND PASTE INTO THE FORM):
HTMLS;
echo $htmls;
// DEFINE A FUNCTION TO CREATE A TEST CASE
function t($str)
{
echo PHP_EOL
. '<br/>'
. '<a href="http://iconoun.com/demo/strtotime.php?s='
. urlencode($str)
. '">'
. $str
. '</a>'
;
}
// USE THE FUNCTION TO CREATE A FEW TEST CASES
t('09/01/2014');
t('09-01-2014');
t('- 3 hours');
t('tomorrow');
t('tomorrow 3:15:25 pm');
t('March 15, 1986');
t('yesterday');
t('yesterday + 1 week');
t('next year');
t('now');
t('now + 627 hours 15 minutes');
t('tomorrow midnight');
t('tomorrow 1:35pm');
t('last Tuesday');
t('three days ago');
t('last Friday + 2 weekdays');
t('- 3 days');
t('A TIME');
t('A BOGUS TIME');
t('s time');
t('t time');
t('u time');
t("Avogadro's Constant");
t("Wednesday November, 10 2010 1:01pm"); echo " a misplaced comma";
t("Wednesday, November 10 2010 1:01pm");
t("First Tuesday 2005"); echo " works, but not the way you might think";
t("Last day of January + 1 Month"); echo " works, but not the way you might think";
t("January 31 + 1 Month"); echo " works, but not the way you might think";
t('-1000000000 seconds'); echo " one billion";
t('+1000000000 seconds');
t('42'); echo " and thanks for all the fish!";
// END OF PAGE
echo '</body></html>';
I promise you it will be worth your time to read the articles I mentioned above. We've all plowed these fields before, and you don't have to reinvent anything here!
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Changed the code so you can do some test changing the querystring value:
http://test.webintenerife.com/check_date.php?date=12/12/2012
http://test.webintenerife.com/check_date.php?date=12/12/2012
Try it like this. You don't have to write a function to decode a date. PHP already has one! It returns the Unix timestamp on success, and FALSE on failure. Easy!
<?php // demo/tofat_a.php
/**
* https://www.experts-exchange.com/questions/28955059/dd-mm-yyyy-php-date-validation.html#a41686243
*
* http://php.net/manual/en/function.strtotime.php
*
* https://www.experts-exchange.com/articles/20920/Handling-Time-and-Date-in-PHP-and-MySQL-OOP-Version.html
* https://www.experts-exchange.com/articles/201/Handling-Date-and-Time-in-PHP-and-MySQL-Procedural-Version.html
*/
error_reporting(E_ALL);
$bogus = 'foo';
if (!$x = strtotime($bogus)) echo "$bogus is not a date ";
$valid = 'July 4, 1776';
if ($x = strtotime($valid)) echo "$valid is a date ";
ASKER
Hmm. How interesting. I tried this which works:
But I still want to format it like this 01/07/2016 or is that not possible? If I try it with your code instead of the dashes it throws the error "is not a date"
$bogus = 'test';
if (!$x = strtotime($bogus)) echo "$bogus is not a date ";
$valid = '01-07-2016';
if ($x = strtotime($valid)) echo "$valid is a date ";
But I still want to format it like this 01/07/2016 or is that not possible? If I try it with your code instead of the dashes it throws the error "is not a date"
Please give yourself a little time to read the man page here carefully and for understanding, then think about the question a little bit more. This stuff has been working correctly in PHP for many, many years. You just need to copy the best practices shown in the PHP.net web site.
http://php.net/manual/en/datetime.formats.date.php
Once you have a Unix timestamp you can use date() to create the readable version of the date in almost any format imaginable.
http://php.net/manual/en/datetime.formats.date.php
Once you have a Unix timestamp you can use date() to create the readable version of the date in almost any format imaginable.
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Besides not copying {1,4} or at least {2,4} to also be able to test for 2 digit years, as we arrived at strtotime() already and it works for Ray and not you, why don't we take a closer look at the manual?
The manual says a / slash automatically turns interpretation to m/d/y instead of d-m-y with dashes or dots. That's why I also though Rays first post was a good answer.
01/07 works in any case, but in general with swapped month and day portions the dates of course can get wrong, eg 15-07-2016 exists, but not 15/07/2016.
Bye, Olaf.
The manual says a / slash automatically turns interpretation to m/d/y instead of d-m-y with dashes or dots. That's why I also though Rays first post was a good answer.
01/07 works in any case, but in general with swapped month and day portions the dates of course can get wrong, eg 15-07-2016 exists, but not 15/07/2016.
Bye, Olaf.
ASKER
Okay, that worked now, Thanks Ray. I am trying to get this validation right but there is obviously something wrong with this as it isn't working.
$bogus = 'foo';
if (empty($_POST["date"])) {
$error .="Please select a date<br>";
}
else if (($date = strtotime($bogus)) === false) {
$error .="That date is invalid.<br>"
}
Do you echo $error?
Bye, Olaf.
Bye, Olaf.
ASKER
Yes, I do.
if ($error != "") {
$error = '<div class="contact-error"><p><strong>There were error(s) in your form:</strong></p>' . $error . '</div>';
echo $error;
Well, that would have been the obvious reason...
So 'foo' is converted to what $date, then?
Bye, Olaf.
So 'foo' is converted to what $date, then?
Bye, Olaf.
ASKER
Sorry, I am not really sure. I was trying to use part of this example:
<?php
$str = 'Not Good';
// previous to PHP 5.1.0 you would compare with -1, instead of false
if (($timestamp = strtotime($str)) === false) {
echo "The string ($str) is bogus";
} else {
echo "$str == " . date('l dS \o\f F Y h:i:s A', $timestamp);
}
?>
Tofat, what about my comment #a41686260?
Well, you have $date computed from 'foo', it is not reported as error, so what does an echo of $date show? That's all I'm asking. If it's empty, you have another indicator of a bogus date. strtotime might not alwways fail, but turn some string to empty/null,0 or an ultimo date, whatever.
Bye, Olaf.
Bye, Olaf.
ASKER
Hi Marco,
Sorry, I was quite keen on the method without using regex which is why I am exploring it. If I don't get a workable answer on that soon then I will revert back to regex and definitely try your solution out.
Sorry, I was quite keen on the method without using regex which is why I am exploring it. If I don't get a workable answer on that soon then I will revert back to regex and definitely try your solution out.
ASKER
Olaf,
I am using ajax for form submission and the reason I can tell the code isn't working is because normally on submit, the errors will appear but now when I submit the loading spinner just spins forever and it does't get further than that. How can I see the echo of date?
I am using ajax for form submission and the reason I can tell the code isn't working is because normally on submit, the errors will appear but now when I submit the loading spinner just spins forever and it does't get further than that. How can I see the echo of date?
ASKER
Just to elaborate:
But I don't know if I am meant to call $valid or not?
$date = ($_POST['date']);
$valid = '01/07/2016';
$bogus = 'foo';
But I don't know if I am meant to call $valid or not?
I wouldn't test that part of code in the whole environment, that's bound to fail. Seems you wired something totally wrong.
Bye, Olaf.
Bye, Olaf.
Straightly doing
Bye, Olaf.
$bogus = 'foo';
if (($date = strtotime($bogus)) === false) echo "That date is invalid.<br>";
Results in that message.Bye, Olaf.
ASKER
I have reverted back to Marco's solution as I am not winning with the other way which I had really wanted to try. I have had 3 people really try to help me now so I don't know how to split up the points. I will try to spread them out fairly between the three of you if that's okay.
Split as you want :)
ASKER
Thanks guys, I appreciate all the assistance!
Very fine. In the end something is working.
Splitting the single values into $matches[2], $matches[1], $matches[3] and putting them into setDate - http://php.net/manual/de/datetime.setdate.php via setDate($matches[3], $matches[2], $matches[1]) may be a solution instead of only checking with checkdate.
That way you accept less formats but if mm/dd/yyyy is your goal you get it that way.
Bye, Olaf.
Splitting the single values into $matches[2], $matches[1], $matches[3] and putting them into setDate - http://php.net/manual/de/datetime.setdate.php via setDate($matches[3], $matches[2], $matches[1]) may be a solution instead of only checking with checkdate.
That way you accept less formats but if mm/dd/yyyy is your goal you get it that way.
Bye, Olaf.
In an online forum like this it's sometimes hard to know the level of experience each participant has. Here are a couple of articles that may make your use of E-E richer and your learning path in PHP smoother. Best of luck with your project, ~Ray
https://www.experts-exchange.com/articles/18625/A-NICE-Approach-to-Dialog-at-E-E.html
https://www.experts-exchange.com/articles/11769/And-by-the-way-I-am-New-to-PHP.html
https://www.experts-exchange.com/articles/18625/A-NICE-Approach-to-Dialog-at-E-E.html
https://www.experts-exchange.com/articles/11769/And-by-the-way-I-am-New-to-PHP.html
To check regex online you can use https://www.regex101.com/