PHP: Validating flexible/incomplete date time strings
Published:
Need to validate some datetime strings, that may or may not be incomplete. Might be for example just a year and a month, while the rest is unknown.
Noting it here in case I need it again. And in case someone else needs it, knows a more efficient/cleaner way, or sees a flaw...
function flexi_time($value): bool
{
$valid = preg_match(
'/^(?<year>\d{4})(?:-(?<month>\d{2})(?:-(?<day>\d{2})(?:[ T](?<hour>\d{2}):(?<min>\d{2})(?::(?<sec>\d{2}))?)?)?)?$/',
$value,
$matches);
if( ! $valid)
return false;
extract($matches);
// Check month
if($month ?? null AND ! between($month, 1, 12))
return false;
// Check date
if($day ?? null AND ! checkdate($month, $day, $year))
return false;
// Check hour
if($hour ?? null AND ! between($hour, 0, 23))
return false;
// Check minute
if($min ?? null AND ! between($min, 0, 59))
return false;
// Check second
if($sec ?? null AND ! between($sec, 0, 59))
return false;
return true;
}
function between($value, $min, $max): bool
{
return $value >= $min && $value <= $max;
}
Test
$dates = [
'foo', // Invalid
'17', // Invalid
'2017',
'2017-01',
'2017-13', // Invalid month
'2017-01-17',
'2017-02-31', // Invalid date
'2017-01-17 20', // Invalid hour without minutes
'2017-01-17 20:00',
'2017-01-17T20:00', // Both space and T allowed as separator
'2017-01-17 20:00:10',
'2017-01-17 25:00:10', // Invalid hour
'2017-01-17 20:70:70', // Invalid minute
'2017-01-17 20:10:70', // Invalid second
];
print_r(array_filter($dates, 'flexi_time'));
Array
(
[2] => 2017
[3] => 2017-01
[5] => 2017-01-17
[8] => 2017-01-17 20:00
[9] => 2017-01-17T20:00
[10] => 2017-01-17 20:00:10
)