Php 如何检查字符串是否为有效的日期、时间或日期时间

Php 如何检查字符串是否为有效的日期、时间或日期时间,php,mysql,validation,datetime,Php,Mysql,Validation,Datetime,当我尝试将一个值放入无效的日期字段时,MySQL似乎使用0000-00-00代替。是否有一种方法可以在不更新日期字段的情况下执行此“检查”?比如说从PHP开始 比如,是否有一种方法可以查询MySQL服务器并询问“嘿,这个日期、时间或日期时间对您有效吗?” 或者有更好的方法吗?如果为MySQL服务器选择不允许无效日期值的服务器模式,则包含这种格式错误的日期表示的查询将导致错误,而不是(无声地)假设0000-00-00 看 e、 g 印刷品 ALLOW_INVALID_DATES: Ok. STRI

当我尝试将一个值放入无效的日期字段时,MySQL似乎使用0000-00-00代替。是否有一种方法可以在不更新日期字段的情况下执行此“检查”?比如说从PHP开始

比如,是否有一种方法可以查询MySQL服务器并询问“嘿,这个日期、时间或日期时间对您有效吗?”


或者有更好的方法吗?

如果为MySQL服务器选择不允许无效日期值的服务器模式,则包含这种格式错误的日期表示的查询将导致错误,而不是(无声地)假设0000-00-00

e、 g

印刷品

ALLOW_INVALID_DATES: Ok.
STRICT_ALL_TABLES: 
Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE[22007]: Invalid datetime format: 1292 Incorrect datetime value: '2010-02-31 12:15:18' for column 'd' at row 1' in [...]

在php中使用此函数检查有效日期:

function valid_date($date) {
    return (preg_match("/^([0-9]{4})-([0-9]{2})-([0-9]{2})$/", $date));
}
或者,正如@VolkerK所说,如果在数据库中插入无效日期,则该日期将存储为0000-00-00,因此您还可以执行以下操作:


SELECT*FROM table WHERE date\u field>'0000-00-00'

您可以根据要使用的格式解析日期,然后调用checkdate测试它是否是有效日期。确保您阅读了上的注释。

您可以只使用“常量”查询,而不使用临时表和测试字段:

mysql> select day('2010-02-31 00:00:00');
+----------------------------+
| day('2010-02-31 00:00:00') |
+----------------------------+
|                       NULL | 
+----------------------------+

一个简单的PHP函数,用于验证MySQL数据类型“date”和“datetime” 在下面的代码示例中(chk_MySQL_Datetime)。它通过使用createFromFormat()来验证 为日期/日期时间创建日期对象如果失败,则为日期/日期时间 这是无效的。如果创建了日期对象,则使用 日期\格式(),并与日期/时间进行比较。 如果字符串相等,则日期/日期时间有效。 如果不相等,则日期/日期时间无效。这个比较 是必需的,因为createFromFormat()将接受2009/02/29 09:85作为有效日期时间 但MySQL不会

下面的代码包括一个示例/测试用例,展示了MySQL数据库的使用和测试。 要使用该示例,您必须将$database->domysql_query()替换为对数据库的调用。 echo的输出作为注释包含在echo语句之后

<?php
/**
 * Returns false if MySQL date or datetime value would be stored as
 * 0000-00-00  or 0000-00-00 00:00:00.
 * @param string $fmt - createFromFormat format of MySQL datetime value
 * to be tested. see http://www.php.net/manual/en/datetime.createfromformat.php
 * @param string $datetime MySQL datetime value
 * to be tested.
 * @return DateTime object formatted according to $fmt or FALSE if not
 * valid MySQL datetime value (would be inserted into the database
 * 0000-00-00 00:00:00);
 */
function chk_MySQL_Datetime($fmt, $datetime) {
    global $fmtdatetime;  // for example only
    $ckdate = DateTime::createFromFormat($fmt, $datetime);
    if ($ckdate !== FALSE) {
        $fmtdatetime = date_format($ckdate, $fmt);
        if ($fmtdatetime != $datetime) {
            $ckdate = FALSE;
        }
    }

    return $ckdate;
}
/*  Example/test of  chk_MySQL_Datetime */
/**
 * Creates table datetimetest if it doesn't exist
 * and insert a record in primary index of type datetime
 * then select record inserted and return result as a formated string.
 * @global type $database - addressibility to database functions
 * @global type $mysqlenum - MySql errornumber of last operation
 * @global type $fmtdatetime - $datetime formatted by date_format
 * @param type $datetime - datetime vale to be set
 * @return string of what was inserted
 */
function insert_in_table($datetime) {
    global $database, $mysqlenum, $fmtdatetime;
    $sql = "CREATE TABLE IF NOT EXISTS `datetimetest` (
  `MySQL_datetime` datetime NOT NULL COMMENT 'datetime created by MySQL',
  `in_datetime` varchar(90) NOT NULL COMMENT 'date time string',
  `fmtdatetime` varchar(90) NOT NULL COMMENT 'Output of createFromFormat',
  PRIMARY KEY (`MySQL_datetime`)
) ;";
    $result = $database->domysql_query($sql, $database->connection, true);

    $sql = "DELETE FROM `datetimetest`  WHERE MySQL_datetime='$datetime' OR `MySQL_datetime` = '0000-00-00 00:00:00'; ";
    $result = $database->domysql_query($sql, $database->connection, false);
    $sql = "INSERT INTO `datetimetest` (MySQL_datetime, in_datetime, fmtdatetime)
       VALUES ('$datetime', '$datetime', '$fmtdatetime')";
    $result = $database->domysql_query($sql, $database->connection, false);
    $sql = "SELECT * FROM `datetimetest`  WHERE MySQL_datetime='$datetime' OR `MySQL_datetime` = '0000-00-00 00:00:00'; ";
    $result = $database->domysql_query($sql, $database->connection, false);
    $contxa = mysql_fetch_assoc($result);

    $ret = " Inserted datetime = " . $contxa['in_datetime'] . "," .
            " MySQL stored " . $contxa['MySQL_datetime'] .
            ", fmtdatetime = " . $contxa['fmtdatetime'] . "<br>";
    return $ret;
}

        global $fmtdatetime;
        echo('<br>');
        $format = 'Y-m-d';
        $datetime = '2009-02-15'; // valid date
        $date = chk_MySQL_Datetime($format, $datetime);
        echo "Format: $format; datetime is " . ($date ? 'valid' : 'invalid' ) . " Expected $datetime is " . $fmtdatetime . "<br>";
 //echo output = Format: Y-m-d; datetime is valid Expected 2009-02-15 is 2009-02-15

        $result = insert_in_table($datetime);
        echo $result . "<br>";
 //echo output = Inserted datetime = 2009-02-15, MySQL stored 2009-02-15 00:00:00, fmtdatetime = 2009-02-15

        $datetime = '2009-02-29'; //invalid date
        $date = chk_MySQL_Datetime($format, $datetime);
        echo "Format: $format; datetime is " . ($date ? 'valid' : 'invalid' ) . " Expected $datetime is " . $fmtdatetime . "<br>";
 //echo output = Format: Y-m-d; datetime is invalid Expected 2009-02-29 is 2009-03-01

        $result = insert_in_table($datetime);
        echo $result . "<br>";
 //echo output =  Inserted datetime = 2009-02-29, MySQL stored 0000-00-00 00:00:00, fmtdatetime = 2009-03-01

        $format = 'Y-m-d H:i';
        $datetime = '2009-02-15 14:20';
        $date = chk_MySQL_Datetime($format, $datetime);
        echo "Format: $format; datetime is " . ($date ? 'valid' : 'invalid' ) . " Expected $datetime is " . $fmtdatetime . "<br>";
//echo output = Format: Y-m-d H:i; datetime is valid Expected 2009-02-15 14:20 is 2009-02-15 14:20

        $result = insert_in_table($datetime);
        echo $result . "<br>";
//echo output = Inserted datetime = 2009-02-15 14:20, MySQL stored 2009-02-15 14:20:00, fmtdatetime = 2009-02-15 14:20

        $datetime = '2009-02-15 14:63';  // invalid time
        $date = chk_MySQL_Datetime($format, $datetime);
        echo "Format: $format; datetime is " . ($date ? 'valid' : 'invalid' ) . " Expected $datetime is " . $fmtdatetime . "<br>";
//echo output = Format: Y-m-d H:i; datetime is invalid Expected 2009-02-15 14:63 is 2009-02-15 15:03

        $result = insert_in_table($datetime);
        echo $result . "<br>";
 //echo output = Inserted datetime = 2009-02-15 14:63, MySQL stored 0000-00-00 00:00:00, fmtdatetime = 2009-02-15 15:03

        $datetime = 'x-02-15 14:59';  // invalid time
        $date = chk_MySQL_Datetime($format, $datetime);
        echo "Format: $format; datetime is " . ($date ? 'valid' : 'invalid' ) . " Expected $datetime is " . $fmtdatetime . "<br>";
 //echo output = Format: Y-m-d H:i; datetime is invalid Expected x-02-15 14:59 is 2009-02-15 15:03

        $result = insert_in_table($datetime);
        echo $result . "<br>";
//echo output =  Inserted datetime = x-02-15 14:59, MySQL stored 0000-00-00 00:00:00, fmtdatetime = 2009-02-15 15:03
?>

我在我的应用程序中使用了这种语法,它的工作很有魅力

SELECT DATE('2013-09-31') AS valid;

我的系统是Win7x64,带有PHP5.5和MySQL 5.6.16

也许你必须用
黑洞
引擎创建一个数据库,请阅读。并检查PDOException引发的异常

$dbh = new PDO('mysql:host=localhost;dbname=test', 'username', 'p@s5W0Rd!!!', array(PDO::ATTR_PERSISTENT => true));

// CREATE DATABASE test;
// CREATE TABLE test.foo ( bar DATETIME ) ENGINE=BLACKHOLE;

try {
    $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

    $dbh->beginTransaction();

    $dateTime = new DateTime();
    $dateTime = $dateTime->format('c');
    $dbh->exec("INSERT INTO foo (bar) VALUES ('".$dateTime."')");
    $dbh->commit();
} catch (PDOException $e) {
    $errorInfo = $dbh->errorInfo();

    if ($e->getCode() === '22007'
        and $dbh->errorCode() === '22007'
        and $errorInfo[0] === '22007'
        and preg_match('/^incorrect datetime/', strtolower($errorInfo[2])) === 1) {

        throw new Exception($errorInfo[2], (int) $e->getCode());
    }
}

由于问题的状态是MySQL,因此这里有一个MySQL解决方案:

由于需要考虑所有可能的日期格式,因此很难验证字段是否为日期。但如果您知道字段日期格式是以下格式之一:

'yyyy-mm-dd'
'yyyy-mm-dd hh:mm:ss'
'yyyy-mm-dd whatever'
此代码将帮助您:

 SELECT count(*) FROM `table` 
 WHERE DATE(STR_TO_DATE(`column`, '%Y-%m-%d')) IS NOT NULL
 AND `column` NOT REGEXP '^[0-9\.]+$'
基本上:

  • 第一个条件告诉您是否是日期,但不幸的是没有排除数字(例如:
    date(stru-TO-date(**1**,%Y-%m-%d))='2001-00-00'
  • 第二种方法确保排除了数字,这使您只能使用符合上述格式的日期
如果
count(*)
>0
那么它是一个日期,如果它是
0
那么它是另一个日期

注意 此方法适用于任何日期格式的字符串,只要您事先知道它们遵循的格式(我知道这种情况并不总是如此,但仍然很有用)。只需在SQL中的查询中替换格式
a priori
这应该只选择有效的
日期时间
s,而且也应该相应地适用于
日期
时间
,但不测试

我没有找到有关转换失败时返回值的
CAST()
的任何文档,但是-可能的失败-返回
NULL

要将“零”日期字符串转换为日期,
CONVERT()
CAST()
返回
NULL
并在启用
NO\u ZERO\u DATE
SQL模式时生成警告 启用

另外,从我的测试来看,
CAST()
anyconvert failure上的行为似乎相同-返回
NULL
,并生成警告

实际上,我在MariaDB 10.0.30上测试了这一点。
选择周(col)不为空作为有效;

或以下其中一项:

SELECT DAYNAME(col) IS NOT NULL AS valid;
SELECT TO_DAYS(col) IS NOT NULL AS valid;
SELECT TO_SECONDS(col) IS NOT NULL AS valid;
SELECT WEEKDAY(col) IS NOT NULL AS valid;
SELECT WEEKOFYEAR(col) IS NOT NULL AS valid;
SELECT YEARWEEK(col) IS NOT NULL AS valid;
我这样做:

if(strtotime(trim($str)) {
    // persist trim($str) in db.        

}

检查值是否为可以使用的日期
day(dateToCheck)=0

尝试使用此…其中DATE_格式(日期('$value'),'%Y-%m-%d')='$value'

使用Perl时,如果失败,$sth->rows将返回零


虽然$sth->rows如果成功将返回非零

,但此函数返回true,并带有“2010-32-56”是的,这将删除错误格式的日期,但不考虑无效日期。已将其用于预检查,除了我使用
\d
而不是
[0-9]
。括号是不需要的:
/^\d{4}-\d{2}-\d{2}$/
很好知道!将研究设置该模式。使用该模式,我将必须实际尝试然后捕获异常。是否有一种方法可以在运行插入或更新之前检查它?据我所知,没有任何方法。但是(虚构的)是否重要函数mysql\u check\u date()返回false或查询执行失败(带有特定的错误代码)?当我需要它来验证用户输入时,那么是的,有点像。特别是如果您想执行“客户端”检查在提交之前使用AJAX或其他方法。奇怪的是,这似乎不起作用。我遇到过一个服务器,其中更新给出了错误1292:
不正确的日期时间值:“2012-09-13T17:58:23+02:00”
,但是
选择日期('2012-09-13T17:58:23+02:00')
给出了13。如果字段的值为“0”,则该操作无效,因为日期('0')=0。您应该添加日期(column)不是null,day(column)是0。另一种方法见我的答案我真的很讨厌如果你通过php在mysql的日期列中插入任何无效值,你会得到一个“0000-00-00”!它要么失败(首选),要么保持为null,要么设置为声明的默认值
SELECT DAYNAME(col) IS NOT NULL AS valid;
SELECT TO_DAYS(col) IS NOT NULL AS valid;
SELECT TO_SECONDS(col) IS NOT NULL AS valid;
SELECT WEEKDAY(col) IS NOT NULL AS valid;
SELECT WEEKOFYEAR(col) IS NOT NULL AS valid;
SELECT YEARWEEK(col) IS NOT NULL AS valid;
if(strtotime(trim($str)) {
    // persist trim($str) in db.        

}