Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
I'm trying to use preg_match to validate that a time input is in this format - "HH:MM"
You can use regular expressions to check that.
for 12-hour:
preg_match("/^(?:1[012]|0[0-9]):[0-5][0-9]$/", $foo)
for 24-hour:
preg_match("/^(?:2[0-3]|[01][0-9]):[0-5][0-9]$/", $foo)
If you use a 24-hour clock going from 01:00 to 24:59, use
preg_match("/^(?:2[0-4]|[01][1-9]|10):([0-5][0-9])$/", $foo)
Simple function that validates a date (and/or time) without throwing exceptions. It takes the expected date format as a parameter:
function isValidDate(string $date, string $format = 'Y-m-d'): bool
{
$dateObj = DateTime::createFromFormat($format, $date);
return $dateObj && $dateObj->format($format) == $date;
}
How it works: it converts the input date into a PHP DateTime object according to the passed $format, then compares this object with the original input date.
If they match, the date is valid and has the expected format.
Some usage examples:
/* Valid Examples: */
isValidDate("2017-05-31");
isValidDate("23:15:00", 'H:i:s');
isValidDate("2017-05-31 11:15:00", 'Y-m-d h:i:s');
/* Invalid: */
isValidDate("2012-00-21");
isValidDate("25:15:00", 'H:i:s');
isValidDate("Any string that's not a valid date/time");
Let's imagine the time you want to check is $timeStr and has to be the format H:i according to the date specs.
Using a regex for this is IMHO silly. This is so much easier to read:
UPDATED
$timeStr = " 02:00"; //example of valid time, note whitespace
test($timeStr);
$timeStr = "23:59"; //valid
test($timeStr);
$timeStr = "24:00"; //invalid
test($timeStr);
$timeStr = "25:00"; //invalid
test($timeStr);
$timeStr = "16:61"; // invalid
test($timeStr);
//tests 23:59 hour format
function test($timeStr){
$dateObj = DateTime::createFromFormat('d.m.Y H:i', "10.10.2010 " . $timeStr);
if ($dateObj !== false && $dateObj && $dateObj->format('G') ==
intval($timeStr)){
//return true;
echo 'valid <br/>';
}
else{
//return false;
echo 'invalid <br/>';
}
}
Function that validates hours, minutes and seconds, according to the desired format:
function validTime($time, $format='H:i:s') {
$d = DateTime::createFromFormat("Y-m-d $format", "2017-12-01 $time");
return $d && $d->format($format) == $time;
}
How to use:
$valid = validTime("23","H");
$valid = validTime("23:59","H:i");
$valid = validTime("23:59:59","H:i:s");
$valid = validTime("23:59:59");
valid = true
$valid = validTime("25","H");
$valid = validTime("01:60","H:i");
$valid = validTime("01:20:61","H:i:s");
$valid = validTime("01:20:61");
valid = false
here is a code that check if the string is an hour between 00:00 and 23:59
$checked = false;
if (preg_match('/^\d{2}:\d{2}$/', $str)) {
if (preg_match("/(2[0-3]|[0][0-9]|1[0-9]):([0-5][0-9])/", $str)) {
$checked = true;
}
}
var_dump($checked );die;
You can do:
if(preg_match('/^(?:[01][0-9]|2[0-3]):[0-5][0-9]$/',$input)) {
// $input is valid HH:MM format.
}
For a 12-hour match that can do am and pm, use this
/^(1[0-2]|0?[1-9]):[0-5][0-9] (AM|PM)$/i
It will handle 01:20 am or 1:20 AM.
The examples above for 12 hour were incorrect because you could potentially do:
00:20
which is not a valid 12 hour format.
Expanding on what #Toskan wrote, you could do this to validate in 00:00 format. Returns true if valid and between 00:00 and 23:59.
This also allows different time formats to be used...
function isTimeValid($time_str, $format = 'H:i')
{
$DateTime = \DateTime::createFromFormat( "d/m/Y {$format}", "10/10/2010 {$time_str}" );
return $DateTime && $DateTime->format( "d/m/Y {$format}" ) == "10/10/2010 {$time_str}";
}
If you aren't requiring preg_match, here is another novel method:
$thetime = "20:15" // set the time
$timecheck = explode(":", filter_var($thetime, FILTER_SANITIZE_URL));
$hourvalid = $minvalid = false;
if (count($timecheck) > 1 && count($timecheck) < 4) {
$hourvalid = ((abs(filter_var($timecheck[0], FILTER_SANITIZE_NUMBER_INT)) < 24)
&& (abs(filter_var($timecheck[0], FILTER_SANITIZE_NUMBER_INT)) === (INT) $timecheck[0]))
? true : false;
$minvalid = ((abs(filter_var($timecheck[1], FILTER_SANITIZE_NUMBER_INT)) < 60)
&& (abs(filter_var($timecheck[1], FILTER_SANITIZE_NUMBER_INT)) === (INT) $timecheck[1]))
? true : false;
}
if ($hourvalid && $minvalid) {//valid time
echo $thetime . " is a valid time<br />";
} else {//invalid time
echo $thetime . " is NOT a valid time<br />";
}
Probably not the most efficient method in the world, but it gets it done. Valid only for times from 00:00 to 23:59. Also, 8:0 validates as a time (assuming you would mean 08:00).
Corrected answer for #Toskan if you only want to validate HH:MM string
protected function isValidTime($timeStr){
$dateObj = DateTime::createFromFormat('d.m.Y H:i', "10.10.2010 " . $timeStr);
$dateObjOffset = DateTime::createFromFormat('d.m.Y H:i', "10.10.2010 " . '24:00');
if($dateObjOffset <= $dateObj){
return false;
}
if ($dateObj !== false) {
return true;
}
else{
return false;
}
}
Based on the Charles's elegant answer with regular expression. If you need a one line validation of both "HH:MM" and "H:MM" (i.e. "9:45"/"09:45") use the following regexp to match 24-hour format:
preg_match("/^(?(?=\d{2})(?:2[0-3]|[01][0-9])|[0-9]):[0-5][0-9]$/", $time)
Explanation
(? stands for conditional subpattern, the syntax is:
(?(condition)yes-pattern|no-pattern)
?= in condition is the regexp assertion
?: in yes-pattern is optional for better performance and you may drop it. This means we don't need any capturing within parentheses (), we need just alternatives feature.
So, we merely describe the following:
If $time string begins with two digits (?=\d{2}), use (2[0-3]|[01][0-9]) pattern to match HH-hour notation ("09:45" case)
otherwise use [0-9] pattern to match H-hour notation ("9:45" case)
UPDATE
As they say, simplicity is the sister of a talent. We don't necessarily need the condition pattern described above. The simpler validation of "HH:MM/H:MM" for 24-hour format:
preg_match("/^(?:2[0-3]|[01][0-9]|[0-9]):[0-5][0-9]$/", $time)
Again, ?: in grouping parentheses () is optional to disable capturing, you can drop it.
So, in this regexp the alternative subpatterns withing () is trying to match two digits hour at the first (20..23) and second (01..19) pattern, then one digit at the last third one (0..9).
In addition, the validation of "HH:MM/H:MM" for 12-hour format:
preg_match("/^(?:0?[1-9]|1[012]):[0-5][0-9]$/", $time);
Here, we're trying to match at first one digit (1..9) with possible preceding zero (0?), and then two digits (10..12).
If you're looking for seconds (24hour). This worked like a charm for me.
$time = "23:59:60";
preg_match("/^([0-1][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])$/", $time)
Another approch without using regex.
if(is_string($foo) && (strlen($foo) == 4 || strlen($foo) == 5) && intval(str_replace(':','',$foo)) > -1 && intval(str_replace(':','',$foo)) < 2360){
stuff to do if valid time
}
else{
stuff to do if invalid time
}
First of all I check if the datatype is string. If not it obvious that it is not a valid time. Then I check if the string has the right lenght of 4 / 5 letters.
With str_replace I remove the ':' and then cast the result to an integer which I could easily compare to the desired time range (in my example 00:00 - 23:59).
Related
Hi I have a function that checks to see if a user input string is a valid date. The user has to input the date in the format 25-January-2018 and it checks to see if it can be converted to the format 25-01-2018. However when I test the function using a date where both the month and day are single digits then it returns false even though a valid date has been entered.
function validateDate($date){
$d = DateTime::createFromFormat('d-F-Y', $date);
return $d && $d->format('j-F-Y') === $date;
}
echo validateDate("03-February-2018"); //Returns false when it should be true
You should replace the j-F-Y with d-F-Y.
j means 1 to 31 while d means 01 to 31 then your two formats are different for the given date.
The following code works:
function validateDate($date){
$d = DateTime::createFromFormat('d-F-Y', $date);
return $d && $d->format('d-F-Y') === $date;
}
var_dump(validateDate("03-February-2018"));
Your function could work :
return $d && $d->format('d-F-Y') === $date;
but if your want to check if it's a valid date use this :
DateTime::createFromFormat('d-F-Y', "03-February") // returns false if not a valid date & Object if valid
Use strtotime() function better.
function validateDate($date){
$timestamp = strtotime($date);
$newDate = date('d-F-Y', $timestamp);
return ($timestamp && $newDate);
}
echo validateDate("03-February-2018");
I'm trying really hard to do some date validation. I have created like 3 different functions, they all work but not in special cases.
The last thing I did was this:
public function valid_date($date, $format = 'd/m/Y'){
$d = DateTime::createFromFormat($format, $date);
return $d && $d->format($format) == $date;
}
I got this function from php site, and like I thought it worked better than mine I replaced it.
The date format the user has to input is dd/mm/YYYY and in the database format is yyyy-mm-dd 00:00:00
When i enter this invalid date: 30/30/1996 the function recognizes it as a valid date. Then I have this other function to explode the "/" and to make it like the database format with "-" and in that function it gives me the error:
DateTime::__construct(): Failed to parse time string (1996-30-30) at position 6 (0): Unexpected character'
public function explodingDates($date){
list($day,$month,$year) = explode('/', $date);
$newDate = $year.'-'.$month.'-'.$day;
return (new \Datetime($newDate));
}
I'm burning my brain here, don't know what else to do for the validation. It also has to be prepared to receive any kind of input (like "askhdakjdh", "123213", "1.25/269") and return an invalid date.
Thanks in advance
Don't explode date strings. Use DateTime::createFromFormat() to create the DateTime object, and use the format() method to convert it into a different format:
function ConvertToMySQLDate($datestr) {
$d = DateTime::createFromFormat('d/m/Y', $datestr);
$valid = $d && $d->format('d/m/Y') == $datestr;
if ($valid) {
return $d->format('Y-m-d');
}
return FALSE;
}
The above function accepts a date string in the format dddd-mm-yyyy, checks if it is valid, and returns the date in MySQL format (yyyy-mm-dd). It returns false if the supplied date is not valid.
Example usage:
var_dump(ConvertToMySQLDate('30/30/1996')); // bool(false)
var_dump(ConvertToMySQLDate('13/12/1996')); // string(10) "1996-12-13"
Demo
Trying to validate a string to check if it has the format 07.05.2013, not sure how to approach it.
Thinking of checking if '.' are the 3rd and 6th characters, then checking if the rest of the characters are digits but I don't know how to achieve that.
If you simply need to parse the date, you can use the date time features of php.
<?php
$date = DateTime::createFromFormat('d.m.Y', '07.05.2013');
echo $date->format('Y-m-d');
?>
Use the DateTime::CreateFromFormat() method. This will validate your input and create a date object at the same time (which you can then use to work with the date).
$dateObj = DateTime::CreateFromFormat('d.m.Y', $inputString);
If the date is invalid or is in the wrong format, $dateObj will be false.
If it is a valid date in the required format, $dateObj will be a DateTime object.
Hope that helps.
if (preg_match('/^\d{2}\.\d{2}\.\d\{4}$/', $yourstring)) {
...
}
This will be true if your string matches expression like dd.dd.dddd where d is a digit.
You can also use the checkdate function:
$date= '07.05.2013';
$date_arr= explode('.', $date);
if (checkdate($date_arr[0], $date_arr[1], $date_arr[2])) {
// validate your date here
}
Something like:
$date = DateTime::createFromFormat('d.m.Y', $yourStringWhichMightBeADate);
if ($date)
{
// it's a date, so use it
}
Or:
$date = DateTime::createFromFormat('m.d.Y', $yourStringWhichMightBeADate);
if ($date)
{
// it's a date, so use it
}
if the month is first rather than the day of month.
SOLUTION 1:
Here's the way I did it, it works with every input you decide to enter (e.g: "12.02.1996", "12.30.1996", "dasdsadas", and so on..)
public function valid_date($inputdate){
$date = $inputdate;
if (strtotime($date)){
if (strpos($date,'.') !== false) {
list($day, $month, $year) = explode('/', $date);
return checkdate($month, $day, $year);
}else{
return false;
}
}else{
return false;
}
}
If input date is 10/10/1996 which is also a valid format, or 10/02/1996, it won't accept them because I'm asking the user to use the format with ".". Just remove the "if" if you don't want to do this validation and that is it.
SOLUTION 2:
Found this at php.net, very clean and interesting!
public function valid_date($date, $format = 'd.m.Y'){
$d = DateTime::createFromFormat($format, $date);
return $d && $d->format($format) == $date;
}
I'm a PHP beginner and been struggling unsuccessfully with the php documentation. Seems a lot of ways to do what I want.
Basically I need a php page to check an "ugly" date/time variable appended to a URL - it must convert it into a usable format and subtract it from the current date/time. If the result is less than 48hrs then the page should redirect to "Page A" otherwise it should redirect to "Page B"
This is what the URL and variable looks like.
http://mysite.com/special-offer.php?date=20130527212930
The $date variable is the YEAR,MONTH,DAY,HOUR,MINUTE,SECOND. I can't change the format of this variable.
I'm guessing PHP can't use that string as it is. So I need to split it somehow into a date format PHP can use. Then subtract that from the current server date/time.
Then put the result into an if/else depending on whether the result is more or less than 48hrs.
Am I right in theory? Can anyone help me with the "practise"?
Thanks!
Take a look at the DateTime class and specifically the createFromFormat method (php 5.3+):
$date = DateTime::createFromFormat('YmdHis', '20130527212930');
echo $date->format('Y-m-d');
You might need to adjust the format depending on the use of leading zeros.
PHP 5 >= 5.3.0
$uglydate = '20130527212930';
// change ugly date to date object
$date_object = DateTime::createFromFormat('YmdHis', $uglydate);
// add 48h
$date_object->modify('+48 hours');
// current date
$now = new DateTime();
// compare dates
if( $date_object < $now ) {
echo "It was more than 48h ago";
}
You can use a regular expression to read your string and construct a meaningful value.
for example
$uglydate = "20130527212930";
preg_match("/([0-9]{4})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})/", $uglydate, $matches);
$datetime = $matches[1] . "-" . $matches[2] . "-" . $matches[3] . " " . $matches[4] . ":" . $matches[5] . ":" . $matches[6];
//then u can use $datetime in functions like strtotime etc
Whoa! you all have WAY too much time on your hands... Nice answers... oh well, i'll pop-in a complete solution...
<?php
$golive = true;
if (preg_match('|^(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})|', $_GET['date'], $matches)) {
list($whole, $year, $month, $day, $hour, $minute, $second) = $matches;
// php: mktime function (using parameters derived
$timestamp = mktime($hour,$minute,$second,$month,$day,$year);
$diff = time()-$timestamp;
$diffInHours = $diff / 3600 ;
// if less, than 48
if ( $diffInHours < 48 ) {
$location = "http://bing.com";
} else {
$location = "http://google.com";
}
//
if ( $golive ) {
header("Location: ".$location);
exit();
} else {
echo "<p>You are would be sending the customer to:<br><strong>$location</strong>";
}
} else {
echo "<p>We're not sure how you got here, but... 'Welcome!'???</p>";
}
That oughta do it.
By the way, on another note, I'd heavily suggest you go back to the sending party of that URL and definitely reconsider how this is being done. As this is VERY easily tweakable (URL date= value), thus not really protecting anything, but merely putting the keys on the front porch next to the 'Guardian Alarms Installed at This House' {sign} :).
Assuming the input is in the correct format (correct number of characters and all of them digits) you'll need 1 substring of length 4 and the rest of lenght 2. For simplicity I'll ignore the first 2 chars (the 20 part from 2013) with substr
$input=substr($input, 2, strlen($input));
Now I can treat all the remaining elements in the string as 2-char pairs:
$mydate=array(); //I'll store everything in here
for($i=0; $i<=strlen($input)-2; $i+=2){
$mydate[$a]=substr($input, $i, $i+2);
$a++;
}
Now I have year, month, day etc. in an array indexed from 0 to 5. For the date difference I'll put the array into mktime:
$timestamp = mktime(mydate[3], mydate[4], mydate[5], mydate[1], mydate[2], mydate[0]);
Finally compare the two timestamps:
if($old_ts - $timestamp > (60*60*48)){
//more than 48 hours
}else{ ... }
New to programming in PHP. Trying to verify input format for a date/time. User input is as follows for Nov 27 2012 at 6 PM '2012-nov-27|6pm'.
Not really sure where to start. Any suggestions? Thanks.
Have a look here for date_parse_from_format documentation and here for general date formatting. Give this a try:
<?php
$date = "2012-nov-27|6pm";
print_r(date_parse_from_format("Y-M-d|ga", $date));
?>
Gangnam OOP style:
$input = '2012-nov-27|6pm';
$date = \DateTime::createFromFormat('Y-M-j ga', str_replace('|', ' ', $input));
if ($date === false) {
throw new \Exception('Invalid date!');
}
NOTE: I experienced an issue by using | in format/date string, so that the str_replace()
NOTE 2: If input day format is 01-31 instead of 1-31, replace the j with a d in createFromFormat() first parameter.
You can use checkdate:
if(checkdate($month, $day, $year)){
echo 'Valid date!';
}
Or, you can convert whatever the user enters with strtotime(). If strtotime can't determine what the date is, it returns bool false.
if(strtotime($dateEntered) !== false){
echo 'Valid date!';
}
Try:
$datetime = "2012-nov-27|6pm";
$unixtime = strtotime( $datetime );
if( is_numeric($unixtime) && $unixtime <= PHP_INT_MAX ) {
//do something if true
} else {
echo "Invalid DateTime";
}
Demo
If you're just looking to test your date for validity, the following will work. Even if you were just looking to test the input format, I suggest you also sanity check the data as well.
$thedate = "2012-nov-27|6pm";
$arryParts = explode("|", $thedate);
$arryDate = date_parse($arryParts[0]);
if(!checkdate($arryDate['month'], $arryDate['day'], $arryDate['year'])) {
/* error handling */
}
/* valid date, continue processing */
If you just want to check the format, use a regex:
$months = 'jan|feb|mar|apr|may|jun|jul|aug|sep|okt|nov|dec';
$pattern = '/([0-9]{4})-('.$months.')-([0-9]{2})\\|([0-9]?[0-9])(am|pm)/';
preg_match($pattern, $input, $matches);
var_dump($matches);
If you really want to check if a specific date/time exists, thing become more complicated. I may be wrong, but I don't think it can be done using PHP date functions, as they are quite tolerant to input errors. Maybe there's a library to do this.