118

エンドユーザーが入力した日付がYYYY-MM-DDにあることを確認しようとしています。正規表現は私の強みではありませんでした。設定したpreg_match()に対して誤った戻り値を取得し続けます。

したがって、以下に詳述する正規表現を台無しにしたと仮定します。

$date="2012-09-12";

if (preg_match("^[0-9]{4}-[0-1][0-9]-[0-3][0-9]$",$date))
    {
        return true;
    }else{
        return false;
    }

何かご意見は?

4

25 に答える 25

219

これを試して。

$date="2012-09-12";

if (preg_match("/^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])$/",$date)) {
    return true;
} else {
    return false;
}
于 2012-11-02T11:33:13.447 に答える
115

これには別のメカニズムを使用する方がおそらく良いでしょう。

最新のソリューション、DateTime

$dt = DateTime::createFromFormat("Y-m-d", $date);
return $dt !== false && !array_sum($dt::getLastErrors());

これにより、入力も検証$dt !== falseされます。指定された形式で日付を解析できることを確認します。array_sumトリックは、PHPが「月のシフト」を行わなかったことを確認するための簡潔な方法です(たとえば、1月32日が2月1日であると考えてください)。詳細については、を参照DateTime::getLastErrors()してください。

explodeとを使用した昔ながらのソリューションcheckdate

list($y, $m, $d) = array_pad(explode('-', $date, 3), 3, 0);
return ctype_digit("$y$m$d") && checkdate($m, $d, $y);

これにより、入力が有効な日付でもあることが検証されます。もちろん、正規表現を使用してこれを行うことはできますが、さらに大騒ぎになるでしょう。2月29日は、正規表現を使用して検証することはできません。

このアプローチの欠点は、どのような状況でも通知を発行せずに、考えられるすべての「悪い」入力を拒否するように非常に注意する必要があることです。方法は次のとおりです。

  • explode3つのトークンを返すように制限されています(入力が「1-2-3-4」の場合、$d「3-4」になるように)
  • ctype_digit入力に数字以外の文字(ダッシュを除く)が含まれていないことを確認するために使用されます
  • array_pad入力が「1-2」の場合に通知を発行しないようにcheckdate、十分な要素が返されるようにするために使用されます(デフォルト値は失敗します)。list()
于 2012-11-02T11:32:04.067 に答える
49

yyyy-mm-dd: /^((((19|[2-9]\d)\d{2})\-(0[13578]|1[02])\-(0[1-9]|[12]\d|3[01]))|(((19|[2-9]\d)\d{2})\-(0[13456789]|1[012])\-(0[1-9]|[12]\d|30))|(((19|[2-9]\d)\d{2})\-02\-(0[1-9]|1\d|2[0-8]))|(((1[6-9]|[2-9]\d)(0[48]|[2468][048]|[13579][26])|((16|[2468][048]|[3579][26])00))\-02\-29))$/g

yyyy / mm / dd: /^((((19|[2-9]\d)\d{2})\/(0[13578]|1[02])\/(0[1-9]|[12]\d|3[01]))|(((19|[2-9]\d)\d{2})\/(0[13456789]|1[012])\/(0[1-9]|[12]\d|30))|(((19|[2-9]\d)\d{2})\/02\/(0[1-9]|1\d|2[0-8]))|(((1[6-9]|[2-9]\d)(0[48]|[2468][048]|[13579][26])|((16|[2468][048]|[3579][26])00))\/02\/29))$/g

mm-dd-yyyy: /^(((0[13578]|1[02])\-(0[1-9]|[12]\d|3[01])\-((19|[2-9]\d)\d{2}))|((0[13456789]|1[012])\-(0[1-9]|[12]\d|30)\-((19|[2-9]\d)\d{2}))|(02\-(0[1-9]|1\d|2[0-8])\-((19|[2-9]\d)\d{2}))|(02\-29\-((1[6-9]|[2-9]\d)(0[48]|[2468][048]|[13579][26])|((16|[2468][048]|[3579][26])00))))$/g

mm / dd / yyyy: /^(((0[13578]|1[02])\/(0[1-9]|[12]\d|3[01])\/((19|[2-9]\d)\d{2}))|((0[13456789]|1[012])\/(0[1-9]|[12]\d|30)\/((19|[2-9]\d)\d{2}))|(02\/(0[1-9]|1\d|2[0-8])\/((19|[2-9]\d)\d{2}))|(02\/29\/((1[6-9]|[2-9]\d)(0[48]|[2468][048]|[13579][26])|((16|[2468][048]|[3579][26])00))))$/g

dd / mm / yyyy: /^(((0[1-9]|[12]\d|3[01])\/(0[13578]|1[02])\/((19|[2-9]\d)\d{2}))|((0[1-9]|[12]\d|30)\/(0[13456789]|1[012])\/((19|[2-9]\d)\d{2}))|((0[1-9]|1\d|2[0-8])\/02\/((19|[2-9]\d)\d{2}))|(29\/02\/((1[6-9]|[2-9]\d)(0[48]|[2468][048]|[13579][26])|((16|[2468][048]|[3579][26])00))))$/g

dd-mm-yyyy: /^(((0[1-9]|[12]\d|3[01])\-(0[13578]|1[02])\-((19|[2-9]\d)\d{2}))|((0[1-9]|[12]\d|30)\-(0[13456789]|1[012])\-((19|[2-9]\d)\d{2}))|((0[1-9]|1\d|2[0-8])\-02\-((19|[2-9]\d)\d{2}))|(29\-02\-((1[6-9]|[2-9]\d)(0[48]|[2468][048]|[13579][26])|((16|[2468][048]|[3579][26])00))))$/g

于 2016-06-03T10:01:29.050 に答える
38

基準:

毎年4で割り切れるのはうるう年です。ただし、400で割り切れる場合を除いて、100で割り切れる場合を除きます。

2004 - leap year - divisible by 4
1900 - not a leap year - divisible by 4, but also divisible by 100
2000 - leap year - divisible by 4, also divisible by 100, but divisible by 400

2月はうるう年で29日、うるう年でない場合は28日です。

4月、6月、9月、11月の30日間

1月、3月、5月、7月、8月、10月、12月の31日間

テスト:

次の日付はすべて検証に合格する必要があります。

1976-02-29
2000-02-29
2004-02-29
1999-01-31

次の日付はすべて検証に失敗するはずです。

2015-02-29
2015-04-31
1900-02-29
1999-01-32
2015-02-00

範囲:

1000年1月1日から2999年12月31日までの日付をテストします。 技術的には、現在使用されているグレゴリオ暦は、大英帝国では1753年に、ヨーロッパ諸国では​​1600年代のさまざまな年にのみ使用されました。それについて心配してください。

うるう年をテストする正規表現:

400で割り切れる年:

1200|1600|2000|2400|2800
can be shortened to:
(1[26]|2[048])00

if you wanted all years from 1AD to 9999 then this would do it:
(0[48]|[13579][26]|[2468][048])00
if you're happy with accepting 0000 as a valid year then it can be shortened:
([13579][26]|[02468][048])00

4で割り切れる年。

[12]\d([02468][048]|[13579][26])

100で割り切れる年:

[12]\d00

100で割り切れない:

[12]\d([1-9]\d|\d[1-9])

100で割り切れるが、400で割り切れない年:

((1[1345789])|(2[1235679]))00

4で割り切れるが、100では割り切れない:

[12]\d([2468][048]|[13579][26]|0[48])

うるう年:

divisible by 400 or (divisible by 4 and not divisible by 100)
((1[26]|2[048])00)|[12]\d([2468][048]|[13579][26]|0[48])

4で割り切れない:

[12]\d([02468][1235679]|[13579][01345789])

うるう年ではありません:

Not divisible by 4 OR is divisible by 100 but not by 400
([12]\d([02468][1235679]|[13579][01345789]))|(((1[1345789])|(2[1235679]))00)

2月を除く有効な月日(MM-DD):

((01|03|05|07|08|10|12)-(0[1-9]|[12]\d|3[01]))|((04|06|09|11)-(0[1-9]|[12]\d|30))
shortened to:
((0[13578]|1[02])-(0[1-9]|[12]\d|3[01]))|((0[469]|11)-(0[1-9]|[12]\d|30))

2月28日:

02-(0[1-9]|1\d|2[0-8])

2月29日:

02-(0[1-9]|[12]\d)

有効日:

(leap year followed by (valid month-day-excluding-february OR 29-day-february)) 
OR
(non leap year followed by (valid month-day-excluding-february OR 28-day-february))

((((1[26]|2[048])00)|[12]\d([2468][048]|[13579][26]|0[48]))-((((0[13578]|1[02])-(0[1-9]|[12]\d|3[01]))|((0[469]|11)-(0[1-9]|[12]\d|30)))|(02-(0[1-9]|[12]\d))))|((([12]\d([02468][1235679]|[13579][01345789]))|((1[1345789]|2[1235679])00))-((((0[13578]|1[02])-(0[1-9]|[12]\d|3[01]))|((0[469]|11)-(0[1-9]|[12]\d|30)))|(02-(0[1-9]|1\d|2[0-8]))))

つまり、1000年1月1日から2999年12月31日までの日付の正規表現がYYYY-MM-DD形式であります。

かなり短くなるのではないかと思いますが、他の人にお任せします。

それはすべての有効な日付と一致します。日付が1つだけで他に何も含まれていない場合にのみ有効にする場合は、次の^( )$ようにラップします。

^(((((1[26]|2[048])00)|[12]\d([2468][048]|[13579][26]|0[48]))-((((0[13578]|1[02])-(0[1-9]|[12]\d|3[01]))|((0[469]|11)-(0[1-9]|[12]\d|30)))|(02-(0[1-9]|[12]\d))))|((([12]\d([02468][1235679]|[13579][01345789]))|((1[1345789]|2[1235679])00))-((((0[13578]|1[02])-(0[1-9]|[12]\d|3[01]))|((0[469]|11)-(0[1-9]|[12]\d|30)))|(02-(0[1-9]|1\d|2[0-8])))))$

オプションの日付エントリに使用する場合(つまり、空白または有効な日付にすることができます)、次^$|のように先頭に追加します。

^$|^(((((1[26]|2[048])00)|[12]\d([2468][048]|[13579][26]|0[48]))-((((0[13578]|1[02])-(0[1-9]|[12]\d|3[01]))|((0[469]|11)-(0[1-9]|[12]\d|30)))|(02-(0[1-9]|[12]\d))))|((([12]\d([02468][1235679]|[13579][01345789]))|((1[1345789]|2[1235679])00))-((((0[13578]|1[02])-(0[1-9]|[12]\d|3[01]))|((0[469]|11)-(0[1-9]|[12]\d|30)))|(02-(0[1-9]|1\d|2[0-8])))))$
于 2015-04-02T16:14:16.963 に答える
19

あなたはそれをこのようにすることができます:

if (preg_match("/\d{4}\-\d{2}-\d{2}/", $date)) {
    echo 'true';
} else {
    echo 'false';
}

しかし、これを使用したほうがよいでしょう:

$date = DateTime::createFromFormat('Y-m-d', $date);
if ($date) {
    echo $date -> format('Y-m-d');
}

この場合、単なる文字列よりも使いやすいオブジェクトが得られます。

于 2012-11-02T11:34:11.417 に答える
11

これは古い質問だと思います。しかし、私には良い解決策があると思います。

$date = "2016-02-21";
$format = "Y-m-d";

if(date($format, strtotime($date)) == date($date)) {
    echo "true";
} else {
    echo "false";
}

あなたはそれを試すことができます。日付を21.02.2016に変更すると、エコーはfalseになります。その後、フォーマットをdmYに変更すると、エコーは真になります。

この簡単なコードを使用すると、正規表現でチェックしなくても、使用されている日付形式をチェックできるはずです。

たぶん、すべての場合にそれをテストする人がいます。しかし、私の考えは一般的に有効だと思います。私にとっては論理的に思えます。

于 2016-02-20T23:11:40.370 に答える
8

preg_matchをcheckdatephp関数で使用できます

$date  = "2012-10-05";
$split = array();
if (preg_match ("/^([0-9]{4})-([0-9]{2})-([0-9]{2})$/", $date, $split))
{
    return checkdate($split[2], $split[3], $split[1]);
}

return false;
于 2012-11-02T11:34:11.850 に答える
6

preg_matchには、区切り文字として/または別の文字が必要です。

preg_match("/^[0-9]{4}-[0-1][0-9]-[0-3][0-9]$/",$date)

また、9999-19-38のような結果にならないように、その日付の有効性を確認する必要があります。

bool checkdate ( int $month , int $day , int $year )
于 2012-11-02T11:34:32.667 に答える
5

一般的な日付形式を検証する関数:

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

実行例:

var_dump(validateDate('2021-02-28')); // true
var_dump(validateDate('2021-02-29')); // false
于 2019-11-29T09:52:18.177 に答える
5

おそらく誰かに役立つ:

$patterns = array(
            'Y'           =>'/^[0-9]{4}$/',
            'Y-m'         =>'/^[0-9]{4}(-|\/)([1-9]|0[1-9]|1[0-2])$/',
            'Y-m-d'       =>'/^[0-9]{4}(-|\/)([1-9]|0[1-9]|1[0-2])(-|\/)([1-9]|0[1-9]|[1-2][0-9]|3[0-1])$/',
            'Y-m-d H'     =>'/^[0-9]{4}(-|\/)([1-9]|0[1-9]|1[0-2])(-|\/)([1-9]|0[1-9]|[1-2][0-9]|3[0-1])\s(0|[0-1][0-9]|2[0-4])$/',
            'Y-m-d H:i'   =>'/^[0-9]{4}(-|\/)([1-9]|0[1-9]|1[0-2])(-|\/)([1-9]|0[1-9]|[1-2][0-9]|3[0-1])\s(0|[0-1][0-9]|2[0-4]):?(0|[0-5][0-9]|60)$/',
            'Y-m-d H:i:s' =>'/^[0-9]{4}(-|\/)([1-9]|0[1-9]|1[0-2])(-|\/)([1-9]|0[1-9]|[1-2][0-9]|3[0-1])\s(0|[0-1][0-9]|2[0-4]):?((0|[0-5][0-9]):?(0|[0-5][0-9])|6000|60:00)$/',
        );
echo preg_match($patterns['Y'], '1996'); // true
echo preg_match($patterns['Y'], '19966'); // false
echo preg_match($patterns['Y'], '199z'); // false
echo preg_match($patterns['Y-m'], '1996-0'); // false
echo preg_match($patterns['Y-m'], '1996-09'); // true
echo preg_match($patterns['Y-m'], '1996-1'); // true
echo preg_match($patterns['Y-m'], '1996/1'); // true
echo preg_match($patterns['Y-m'], '1996/12'); // true
echo preg_match($patterns['Y-m'], '1996/13'); // false
echo preg_match($patterns['Y-m-d'], '1996-11-1'); // true
echo preg_match($patterns['Y-m-d'], '1996-11-0'); // false
echo preg_match($patterns['Y-m-d'], '1996-11-32'); // false
echo preg_match($patterns['Y-m-d H'], '1996-11-31 0'); // true
echo preg_match($patterns['Y-m-d H'], '1996-11-31 00'); // true
echo preg_match($patterns['Y-m-d H'], '1996-11-31 24'); // true
echo preg_match($patterns['Y-m-d H'], '1996-11-31 25'); // false
echo preg_match($patterns['Y-m-d H:i'], '1996-11-31 2400'); // true
echo preg_match($patterns['Y-m-d H:i'], '1996-11-31 24:00'); // true
echo preg_match($patterns['Y-m-d H:i'], '1996-11-31 24:59'); // true
echo preg_match($patterns['Y-m-d H:i'], '1996-11-31 24:60'); // true
echo preg_match($patterns['Y-m-d H:i'], '1996-11-31 24:61'); // false
echo preg_match($patterns['Y-m-d H:i'], '1996-11-31 24:61'); // false
echo preg_match($patterns['Y-m-d H:i:s'], '1996-11-31 24:6000'); // true
echo preg_match($patterns['Y-m-d H:i:s'], '1996-11-31 24:60:00'); // true
echo preg_match($patterns['Y-m-d H:i:s'], '1996-11-31 24:59:59'); // true
echo preg_match($patterns['Y-m-d H:i:s'], '1996-11-31 24:59:60'); // false
echo preg_match($patterns['Y-m-d H:i:s'], '1996-11-31 24:60:01'); // false
于 2020-02-21T03:32:28.580 に答える
4

次のようにすることもできます。

if (DateTime::createFromFormat('Y-m-d', $date)->format('Y-m-d') === $date) {

    // date is correctly formatted and valid, execute some code

}

これにより、形式だけでなく、日付自体の有効性もチェックされDateTimeます。これは、有効な日付のみが作成され、入力と一致する必要があるためです。

于 2018-02-12T15:47:44.433 に答える
4

あなたが使用することができます

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

$date="2012-09-12";    
echo validateDate($date, 'Y-m-d'); // true or false
于 2018-04-13T13:38:09.127 に答える
2

そのタイプの日付と一致させる場合は、次を使用します。

preg_match("~^\d{4}-\d{2}-\d{2}$~", $date)
于 2012-11-02T11:34:53.157 に答える
2

これにより、形式が有効かどうか、および入力日が有効かどうかがわかります。

    $datein = '2012-11-0';

    if(preg_match('/^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])$/', $datein)){
        echo 'good';
    }else{
        echo 'no good';
    }
于 2012-11-02T11:47:23.220 に答える
2

YYYY-MM-DD1行のステートメントで日付を確認および検証します

function isValidDate($date) {
    return preg_match("/^(\d{4})-(\d{1,2})-(\d{1,2})$/", $date, $m)
        ? checkdate(intval($m[2]), intval($m[3]), intval($m[1]))
        : false;
}

出力は次のようになります。

var_dump(isValidDate("2018-01-01")); // bool(true)
var_dump(isValidDate("2018-1-1"));   // bool(true)
var_dump(isValidDate("2018-02-28")); // bool(true)
var_dump(isValidDate("2018-02-30")); // bool(false)

先行ゼロのない日と月は許可されます。これを許可したくない場合、正規表現は次のようになります。

"/^(\d{4})-(\d{2})-(\d{2})$/"
于 2017-11-19T16:22:33.943 に答える
2

フォーマット1:$ format1 = "2012-12-31";

フォーマット2:$ format2 = "31-12-2012";

if (preg_match("/^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])$/",$format1)) {
    return true;
} else {
    return false;
}

if (preg_match("/^(0[1-9]|[1-2][0-9]|3[0-1])-(0[1-9]|1[0-2])-[0-9]{4}$/",$format2)) {
    return true;
} else {
    return false;
}
于 2019-07-25T11:42:47.307 に答える
1

それはすべて、この関数をどれだけ厳密にするかによって異なります。たとえば、12か月を超える月と31日を超える日を許可したくない場合(月に依存しないため、date-logicを作成する必要があります)、かなり複雑になる可能性があります。

function checkDate($date)
{
  $regex = '/^' . 
    '(' .

    // Allows years 0000-9999
    '(?:[0-9]{4})' .
    '\-' .

    // Allows 01-12
    '(?:' .
    '(?:01)|(?:02)|(?:03)|(?:04)|(?:05)|(?:06)|(?:07)|(?:08)|(?:09)|(?:10)|' .
    '(?:11)|(?:12)' .
    ')' .
    '\-' .

    // Allows 01-31
    '(?:' .
    '(?:01)|(?:02)|(?:03)|(?:04)|(?:05)|(?:06)|(?:07)|(?:08)|(?:09)|(?:10)|' .
    '(?:11)|(?:12)|(?:13)|(?:14)|(?:15)|(?:16)|(?:17)|(?:18)|(?:19)|(?:20)|' .
    '(?:21)|(?:22)|(?:23)|(?:24)|(?:25)|(?:26)|(?:27)|(?:28)|(?:29)|(?:30)|' .
    '(?:31)' .
    ')' .

    '$/';

  if ( preg_match($regex, $date) ) {
    return true;
  }

  return false;
}

$result = checkDate('2012-09-12');

個人的に私はただ行きます:/^([0-9]{4}\-([0-9]{2}\-[0-9]{2})$/

于 2012-11-02T12:37:22.760 に答える
1

phpで日付を操作するには、php標準に従う必要があります。これにより、指定された正規表現により、PHPで操作できる有効な日付が保証されます。

    preg_match("/^([0-9]{4})-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])$/",$date)
于 2014-09-23T04:49:48.840 に答える
1

役立つ場合は、jnY形式の正規表現を次に示します(年は2018年より大きくする必要があります)。

if (preg_match('/^([1-9]|[1-2][0-9]|[3][0-1])\-([1-9]|[1][0-2])\-(?:20)([1][8-9]|[2-9][0-9])$/', $date)) {
   // Do stuff
}
于 2018-10-07T10:18:04.773 に答える
1

Laravel 5.7および日付形式から:2019年12月31日

function checkDateFormat(string $date): bool
{
    return preg_match("/^(0[1-9]|1[0-2])\/(0[1-9]|[1-2][0-9]|3[0-1])\/[0-9]{4}$/", $date);
}
于 2019-06-26T10:30:55.877 に答える
1

私は「日付を検証する方法」を検索していて、この解決策を見つけました。古いですが、phpで日付を検証するために使用できる方法を以下で共有します。

checkdate('01', '31', '2019')
于 2019-11-21T09:29:48.633 に答える
1

以下は、数字YYYY(1900-2099)-MM(01-12)-DD(01-31)を保証し、日付の正確さのためにcheckdate()関数を利用します(例:2月29日)。

$date_pattern = '/^(19|20)\d{2}\-(0[1-9]|1[0-2])\-(0[1-9]|[12][0-9]|3[01])$/';

if (empty($date) || (!preg_match("$date_pattern", $date, $m) || (!checkdate($m[2], $m[3], $m[1])))) {
    $echo 'Invalid Start date e.g. YYYY-MM-DD';
}

日付パターンと年の範囲を変更するには:

//パターンDD/MM / YYYYここで、DD(01-31)、MM(01-12)、およびYYYY(1950-2099)&数字である必要があります-checkdate()をに置き換えます!checkdate($m[2], $m[1], $m[3]

//年の範囲を拡張するには例:1900-2099 / ^(0 [1-9] | [12] [0-9] | 3 [01])/(0 [1-9] | 1 [0-2]) /(19 | 20)\ d {2} $ /-checkdate()をに置き換えます!checkdate($m[2], $m[1], $m[3]

于 2021-09-30T10:48:43.373 に答える
0

このメソッドは、PHPで日付を検証するのに役立ちます。現在の方法はmm/dd/yyyy形式です。explodeの形式と区切り文字に従って、 checkdateのパラメーターシーケンスを更新する必要があります。

    function isValidDate($dt)
    {
        $dtArr = explode('/', $dt);
        if (!empty($dtArr[0]) && !empty($dtArr[1]) && !empty($dtArr[2])) {
            return checkdate((int) $dtArr[0], (int) $dtArr[1], (int) $dtArr[2]);
        } else {
            return false;
        }
    }
于 2017-05-29T11:52:47.130 に答える
0

[Symfony 4.1.2を使用している場合は、これを試してください] [1]

  $validDate = explode("-",$request->get('date'));
        if (checkdate(filter_var($validDate[1],FILTER_SANITIZE_NUMBER_INT),filter_var($validDate[0],FILTER_SANITIZE_NUMBER_INT),filter_var($validDate[2],FILTER_SANITIZE_NUMBER_INT))){
            $date = date_create(filter_var($request->get('date'),FILTER_SANITIZE_SPECIAL_CHARS));
        }else{
            return $this->redirectToRoute('YOUR_ROUTE');
        }
于 2019-01-31T14:08:43.563 に答える
0

より実用的なパターンは次のようになります

$date="2012-09-12";

if (preg_match("/^(20[0-9]{2})-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])$/",$date)) {
    return true;
} else {
    return false;
}

これにより、9999-09-12のような値を入力できなくなります。

于 2021-04-09T19:25:01.173 に答える