检查字符串是 Carbon 中的有效日期,带有溢出和相对格式标志

问题描述

我需要一个这样的方法

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() 构造函数内部),此行为不是库代码的一部分,因此如果您想限制它,则由您的业务端代码决定允许哪些输入以及决定如何检测发生的溢出。

一般来说,不将所有这些检查混合在一个函数中与一个布尔标志矩阵进行各种检查组合会更安全,我宁愿将它们分开。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...