web-dev-qa-db-ja.com

文字列が有効なDATE、TIME、またはDATETIMEかどうかを確認する方法

無効なDATEフィールドに値を入力しようとすると、MySQLは代わりに0000-00-00を使用するようです。 DATEフィールドを更新せずにこの「チェック」を行う方法はありますか?そして、例えばPHPからそれを行うには?

同様に、MySQLサーバーにクエリを実行して「こんにちは、このDATE、TIME、またはDATETIMEは有効ですか?」

それともそれを行うためのより良い方法がありますか?

19
Svish

無効な日付値を許可しないMySQLサーバーのサーバーモードを選択した場合、そのような不正な日付表現を含むクエリは、0000-00-00と(サイレントに)想定する代わりにエラーを引き起こします。
参照 http://dev.mysql.com/doc/refman/5.0/en/server-sql-mode.html

例えば.

$pdo = new PDO('mysql:Host=localhost;dbname=test', 'localonly', 'localonly'); 
$pdo->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );

$pdo->exec('CREATE TEMPORARY TABLE foo (id int auto_increment, d datetime, primary key(id))');

$query = "INSERT INTO foo (d) VALUES ('2010-02-31 12:15:18')";
foreach( array('ALLOW_INVALID_DATES', 'STRICT_ALL_TABLES') as $mode ) {
  echo $mode, ": "; flush();
  $pdo->exec("SET SESSION sql_mode='$mode'");
  $pdo->exec($query);
  echo "Ok.\n";
}

プリント

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 [...]
2
VolkerK

私は自分のアプリケーションでこの構文を使用し、それは魅力のように機能します!

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

私のシステムはPHP 5.5およびMySQL 5.6.16のWin7x64です。

7
Abbas

使用する形式に従って日付を解析し、checkdateを呼び出して、それが有効な日付かどうかをテストできます。 http://php.net/manual/en/function.checkdate.php に関するコメントを必ずお読みください。

6
wimvds

質問には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(STR_TO_DATE(**1**, '%Y-%m-%d')) = '2001-00-00'
  • 2番目は、数値が除外されることを保証します。これにより、上記の形式に従う日付のみが残ります。

count(*)が_>0_の場合は日付で、_0_の場合は別の日付です。

この方法は、日付の文字列がどの形式に従うかを事前に知っている限り、どの形式の文字列でも機能します(常にそうであるとは限りませんが、役に立ちます)。クエリの_a priori_形式を置き換えるだけです

4
BassMHL

一時テーブルやテストフィールドを使用せずに、「定数」クエリを使用できます。

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

SELECT WEEK(col) IS NOT NULL AS valid;

または次のいずれか:

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;
2
Timo Kähkönen

私はこれをします:

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

}
1
Mubashar Abbas

値が日付かどうかを確認するには、day(dateToCheck) = 0を使用できます

DATETIME-SQLで

_SELECT your_unreliable_datetime_column, CAST(your_unreliable_datetime_column as DATETIME)
FROM some_cool_table
WHERE
CAST(your_unreliable_datetime_column as DATETIME) IS NOT NULL
AND
your_unreliable_datetime_column = CAST(your_unreliable_datetime_column as DATETIME)
_

これは、有効なDATETIMEsのみを選択する必要があります。また、DATEおよびTIMEに適切に適用される必要があります、ただしテストされていません...

変換エラー時のCAST()戻り値に関するドキュメントは見つかりませんでしたが、 ドキュメントは特殊なケースをカバーしています -起こりうるエラー-NULLを返します:

「ゼロ」の日付文字列を日付に変換する場合、CONVERT()およびCAST()NULLを返し、_NO_ZERO_DATE_ SQLモードが有効な場合に警告を生成します。

また、私のテストからそれseemsCAST()any変換失敗時に同じように動作する-NULLを返す警告を生成します。

実際にこれを_MariaDB 10.0.30_でテストしました

0
jave.web

多分あなたはBLACKHOLEエンジンでデータベースを作成する必要があります ここ を読んでください。そして、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());
    }
}
0
krisanalfa

これを使ってみてください... WHERE DATE_FORMAT(DATE( '$ value')、 '%Y-%m-%d')= '$ value'

perlを使用している場合、$ sth-> rowsは失敗するとゼロを返します

一方、$ sth-> rowsは、成功するとゼロ以外を返します

0
PRConnect

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_field > '0000-00-00'

0
fire

「日付」と「日付時刻」のMySQLデータ型を検証する単純なPHP関数は、次のコードサンプルにあります(chk_MySQL_Datetime)。createFromFormat()を使用して検証し、これが失敗した場合、日付/日付時刻。日付/日付時刻は無効です。日付オブジェクトが作成された場合、date_format()で作成され、日付/時刻と比較されたフォーマット済み文字列。文字列が等しい場合、日付/日付時刻は有効です。等しくない場合、日付/日付時刻は無効です。createFromFormat()は2009/02/29 09:85を有効な日付時刻として受け入れますが、MySQLは受け入れないため、この比較が必要です。

次のコードには、MySQLデータベースに対する使用法とテストを示すサンプル/テストケースが含まれています。この例を使用するには、$ database-> domysql_query()をデータベースの呼び出しに置き換える必要があります。エコーの出力は、エコーステートメントの直後にコメントとして含まれます。

<?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
?>
0
user3342806