【问题标题】:Validate string input for DateTime::modify()验证 DateTime::modify() 的字符串输入
【发布时间】:2016-04-26 06:11:18
【问题描述】:

我有一个场景,发送到DateTime::modify($string)$string 变量是从用户编辑的数据库中读取的,我如何验证$stringDateTime::modify() 的正确字符串?

【问题讨论】:

标签: php database validation date


【解决方案1】:

试试这个函数来根据格式验证时间戳字符串

function validateDate($date, $format = 'Y-m-d H:i:s')
{
    $d = DateTime::createFromFormat($format, $date);
    return $d && $d->format($format) == $date;
}

函数是从 answerphp.net 复制而来的

【讨论】:

  • 在应用修改功能之前,我正在使用此功能检查日期的格式。我需要验证修改正确格式日期的字符串,该字符串应验证为 DateTime::modify() 可以理解的字符串。
  • 从你的函数内部调用这个函数
  • 为什么一定要加$d->format($format) == $date
  • @systemovich 确保您能够从发送的字符串构造正确的时间戳,从而确保正确的字符串
【解决方案2】:

在将用户输入保存到数据库之前检查用户输入通常是最佳做法,这样您就可以在输出时对其充满信心。

您也可以使用 try/catch 块:

try {
    $date = new DateTime('2016-12-12');
    $date->modify('+1 dayBLA');
    echo $date->format('Y-m-d');
} catch (Exception $e) {
    echo 'Caught exception: ',  $e->getMessage(), "\n";
}

编辑:查看此内容后,如果传递给modify 的字符串无效(不是我最初设想的日期字符串),您的代码将抛出Warning 而不是异常。

可能能够触发Warning 暂时被视为set_error_handler 的异常。

function warning_handler($errno, $errstr, $errfile, $errline, array $errcontext) {
    throwErrorException($errstr, 0, $errno, $errfile, $errline);
}
set_error_handler('warning_handler', E_WARNING);

try {
    $date = new DateTime('2016-12-12');
    $date->modify('+1 daybla');
    echo $date->format('Y-m-d');
} catch (Exception $e) {
    echo 'Caught exception: ',  $e->getMessage(), "\n";
}

restore_error_handler();

但是,这开始看起来有点讨厌。比较调用 modify 方法之前和之后的日期以查看它们是否不同可能会更清晰(在您的代码中,而不是在您的日志中)。

$date = new DateTime('2016-12-12');
$origDate = clone $date; //I believe this will get you an independent object
$date->modify('+1 daybla');
if ($origDate == $date) {
    echo "Bad value passed to modify, probably a warning in the logs :(";
}

【讨论】:

  • 我同意在输入数据库之前应该检查输入,我会这样做,但如果可能的话,我也想在这方面进行验证——以防万一。我尝试按照您的建议添加尝试和捕获,但是当修改失败时仍然会发出警告?
  • 我也只是注意到了这一点 - 环顾四周后,我没有看到一个很好的方法来做到这一点。显然,您传递给modify 的字符串上的正则表达式是最好的,但该方法采用的字符串似乎非常不同。也许您可以通过对用户输入进行更多限制来解决,例如三个输入:1)+/-,2)hour/day3)计数(一个整数)。我编辑了答案,您可以尝试其他一些选项 - 祝你好运!
【解决方案3】:

您可以这样做,并在将字符串传递给您的实际日期之前调用它:

function modifyIsValid($modifyString) {
    $d = new DateTime();
    $isValid = $d->modify($modifyString);

    if ($isValid === false) {
        return false;
    }

    return true;
}

->modify() 返回 false 是传递的字符串无效,虽然它也会抛出一个不理想的E_Warning

$d = new DateTime();
$string = 'not a valid modifier';

if (modifyIsValid($string)) {
    // Continue 
}  else {
    // Print a friendly error message.
}

您可以在手册中找到有关它的更多信息:http://php.net/manual/en/datetime.modify.php

希望对你有帮助。

【讨论】:

  • 这看起来是验证字符串的好方法,但我需要处理警告,这是一种可以简单地抑制警告的情况吗?
  • @ChristopherKarlsson 这可能是消除错误的一种潜在方法,毕竟即使您正在抑制错误,您仍在处理它,所以应该没问题。另一种执行检查的方法很可能使用正则表达式来验证字符串是否符合此处找到的所有有效格式:php.net/manual/en/datetime.formats.php
  • 我会接受这个答案,因为它似乎是您可以进行干净验证的最接近的方法,即使它会引发警告,我也会按照@pherris 答案中的建议处理警告。
【解决方案4】:

在这里聚会有点晚了,这对我来说非常适合......

function isDateModifyValid($String)
{
    if (strlen($String) == 0) { return false; }
    $now = new \DateTime(null, new \DateTimeZone("UTC"));
    $rtn = false; // Default return value
    @$now->modify($String) && $rtn = true; 
     // If modify($string) fails, $rtn won't set to true, else $rtn will set to true
    // ^ ^ @ suppress error
    return $rtn;
}

//TEST DATA
foreach (array("+1 hour", "+2 hour, -5 minutes", "12:00", "dsfv", "13:00, + 1 hour", "Yesterday, 12:00", "Neext weeekc", "Next month") as $testString)
{
    if (isDateModifyValid($testString))
    {
        echo "VALID ::: $testString\n";
    } else {
        echo "INVALID ::: $testString\n";
    }
}

VALID ::: +1 hour VALID ::: +2 hour, -5 minutes VALID ::: 12:00 INVALID ::: dsfv VALID ::: 13:00, + 1 hour VALID ::: Yesterday, 12:00 INVALID ::: Neext weeekc VALID ::: Next month

【讨论】:

  • 你的答案添加了什么其他人没有?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-06-12
  • 2012-05-10
  • 1970-01-01
  • 2011-12-17
  • 2015-04-29
  • 2010-09-28
  • 1970-01-01
相关资源
最近更新 更多