developer tip

날짜를 확인하는 PHP Regex는 YYYY-MM-DD 형식입니다.

optionbox 2020. 10. 6. 08:06
반응형

날짜를 확인하는 PHP Regex는 YYYY-MM-DD 형식입니다.


최종 사용자가 입력 한 날짜가 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;
    }

이견있는 사람?


이 시도.

$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;
}

이를 위해 다른 메커니즘을 사용하는 것이 좋습니다.

다음과 같은 최신 솔루션 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().

explodecheckdate다음을 사용한 구식 솔루션 :

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_padcheckdate입력이 "1-2"인 list()경우 알림을 내 보내지 않도록 충분한 요소가 리턴되었는지 확인하기 위해 (실패 를 유발하는 기본값과 함께) 사용됩니다.

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


기준 :

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))

28 일이 포함 된 2 월 :

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

29 일이 포함 된 2 월 :

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]))))

그래서 거기에 YYYY-MM-DD 형식의 1000 년 1 월 1 일과 2999 년 12 월 31 일 사이의 날짜에 대한 정규식이 있습니다.

상당히 단축 될 수 있다고 생각하지만 다른 사람에게 맡기겠습니다.

유효한 모든 날짜와 일치합니다. 날짜가 하나만 있고 다른 것이없는 경우에만 유효하도록하려면 다음 ^( )$과 같이 래핑합니다 .

^(((((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])))))$

다음과 같이 만들 수 있습니다.

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');
}

이 경우 문자열보다 사용하기 쉬운 개체를 얻을 수 있습니다.


checkdate php 함수와 함께 preg_match를 사용할 수 있습니다.

$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;

나는 이것이 오래된 질문이라는 것을 알고 있습니다. 하지만 좋은 해결책이 있다고 생각합니다.

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

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

시도해 볼 수 있습니다. 날짜를 21.02.2016으로 변경하면 에코가 거짓입니다. 그 후 형식을 dmY로 변경하면 에코가 참입니다.

이 쉬운 코드를 사용하면 정규식에서 확인하지 않고도 사용되는 날짜 형식을 확인할 수 있습니다.

모든 경우에 테스트 할 사람이있을 수 있습니다. 하지만 내 생각은 일반적으로 유효하다고 생각합니다. 나에게는 논리적으로 보인다.


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 )

당신이 사용할 수있는

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

다음과 같이 할 수도 있습니다.

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

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

}

형식뿐만 아니라 날짜 자체의 유효성도 확인합니다. DateTime유효한 날짜 만 생성하고 입력과 일치해야하기 때문입니다.


If you want to match that type of date, use:

preg_match("~^\d{4}-\d{2}-\d{2}$~", $date)

This should tell you if the format is valid and if the input date is valid.

    $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';
    }

Check and validate YYYY-MM-DD date in one line statement

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;
}

The output will be:

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)

Day and month without leading zero are allowed. If you don't want to allow this, the regexp should be:

"/^(\d{4})-(\d{2})-(\d{2})$/"

If it is of any help, here is a regex for j-n-Y format (year has to be greater than 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
}

It all depends on how strict you want this function to be. For instance, if you don't want to allow months above 12 and days above 31 (not depending on the month, that would require writing date-logic), it could become pretty complicated:

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');

Personally I'd just go for: /^([0-9]{4}\-([0-9]{2}\-[0-9]{2})$/


To work with dates in php you should follow the php standard so the given regex will assure that you have valid date that can operate with PHP.

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

This method can be useful to validate date in PHP. Current method is for mm/dd/yyyy format. You have to update parameter sequence in checkdate as per your format and delimiter in explode .

    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;
        }
    }

[If you use Symfony 4.1.2 try this][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');
        }

From Laravel 5.7 and date format i.e.: 12/31/2019

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);
}

Format 1 : $format1 = "2012-12-31";

Format 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;
}

참고URL : https://stackoverflow.com/questions/13194322/php-regex-to-check-date-is-in-yyyy-mm-dd-format

반응형