问题描述
function check_date_format($date,$allowOverflow = false,$allowRelativeFormats = false)
如果字符串根据布尔标志是正确的日期/时间,则返回 bool。
其中 $allowOverflow = false
表示像 2020-13-13 (2021-01-13) 这样溢出的日期不正确,
$allowRelativeFormats = false
表示“今天”、“明天”、“x 天前”等相对日期不正确
是否有可能使用 Carbon / DateTime 类编写该函数,而无需在该函数内定义自己的数组,例如 $availableFormats
?
理解我的预期结果的示例:
check_date_format('asdgasd'); // false
check_date_format('2020-02-01'); // true
check_date_format('2020-02-30'); // false
check_date_format('2020-02-30',true); // true
check_date_format('10:00'); // true
check_date_format('tomorrow'); // false
check_date_format('tomorrow',false,true); // true
check_date_format('Now'); // false
我尝试以这种方式使用 date_parse()
:
function check_date_format($date,$allowRelativeFormats = false)
{
$dateInfo = date_parse($date);
$isCorrectDate = $dateInfo['error_count'] === 0;
if ($isCorrectDate) {
$isRelative = array_key_exists('relative',$dateInfo);
$isOverflowed = $dateInfo['warning_count'] > 0;
if (!$allowOverflow && $isOverflowed) {
return false;
}
if (!$allowRelativeFormats && ($isRelative || strtolower(trim($date)) === 'Now')) {
return false;
}
return true;
}
return false;
}
但此解决方案假定“警告”意味着我不确定的溢出。
解决方法
可以通过简单地尝试来检查是否可以创建日期:
try {
$date = @Carbon::parse('asdgasd');
} catch (InvalidFormatException $_) {
$date = false;
}
$canBeCreated = ($date !== false);
Carbon 支持检查字符串是否为相对格式:
$hasRelativeFormat = Carbon::hasRelativeKeywords('tomorrow');
但是对于溢出,没有办法一次处理所有格式。例如,如果您有严格的格式输入,您可以检查是否发生溢出:
Carbon::parse('2020-02-01')->format('Y-m-d') === '2020-02-01'; // true => no overflow
Carbon::parse('2020-02-30')->format('Y-m-d') === '2020-02-30'; // false => overflow
但是如果允许使用 "January 1st 2020"
,这个技巧就不再可能了。并且溢出实际上发生在 PHP timelib 扩展内部(在 new DateTime()
构造函数内部),此行为不是库代码的一部分,因此如果您想限制它,则由您的业务端代码决定允许哪些输入以及决定如何检测发生的溢出。
一般来说,不将所有这些检查混合在一个函数中与一个布尔标志矩阵进行各种检查组合会更安全,我宁愿将它们分开。