Php 如何检查字符串是否为有效的日期、时间或日期时间
当我尝试将一个值放入无效的日期字段时,MySQL似乎使用0000-00-00代替。是否有一种方法可以在不更新日期字段的情况下执行此“检查”?比如说从PHP开始 比如,是否有一种方法可以查询MySQL服务器并询问“嘿,这个日期、时间或日期时间对您有效吗?”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
看 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.
}