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.
开发者_如何学Go Improve this questionI'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).
精彩评论