날짜 문자열이 해당 형식의 유효한 날짜인지 올바르게 판별하십시오.


184

API에서 날짜 문자열을 받고 있는데 형식이 yyyy-mm-dd입니다.

현재 정규식을 사용하여 문자열 형식의 유효성을 검사하지만 정상적으로 작동하지만 문자열에 따라 올바른 형식 일 수는 있지만 실제로 유효하지 않은 날짜가있는 경우를 볼 수 있습니다. 예 2013-13-01를 들어.

PHP에서 문자열을 가져 와서 2013-13-01형식에 유효한 날짜인지 아닌지 알려주 는 더 좋은 방법이 yyyy-mm-dd있습니까?


의 가능한 중복 PHP 날짜 확인
비벡 Athalye

2
어쨌든 여기에 대한 답변이 훨씬 낫습니다.
Sebastien

답변:


454

DateTime이 목적으로 수업을 사용할 수 있습니다 .

function validateDate($date, $format = 'Y-m-d')
{
    $d = DateTime::createFromFormat($format, $date);
    // The Y ( 4 digits year ) returns TRUE for any integer with any number of digits so changing the comparison from == to === fixes the issue.
    return $d && $d->format($format) === $date;
}

[ 이 답변 에서 가져온 기능 . 또한에 php.net . 글라 비치가 처음 썼습니다 . ]


테스트 사례 :

var_dump(validateDate('2013-13-01'));  // false
var_dump(validateDate('20132-13-01')); // false
var_dump(validateDate('2013-11-32'));  // false
var_dump(validateDate('2012-2-25'));   // false
var_dump(validateDate('2013-12-01'));  // true
var_dump(validateDate('1970-12-01'));  // true
var_dump(validateDate('2012-02-29'));  // true
var_dump(validateDate('2012', 'Y'));   // true
var_dump(validateDate('12012', 'Y'));  // false

데모!


14
PHP 5.2.x를 사용 strtotime하는 경우 유닉스 타임 스탬프 date('Y-m-d', $t)를 얻은 다음 문자열 날짜를 얻는 데 사용해야 합니다. 그런 다음이 답변과 마찬가지로 비교하십시오.
pedromanoel

2
@pedromanoel : 표준 날짜 / 시간 입력의 경우을 사용할 수 strtotime있지만 strtotime인식 할 수없는 비표준 형식의 경우 다른 솔루션이 필요합니다. 그리고 PHP 버전 5.2 지원은 2011 년 1 월에 중단되었으며, 5.3 지원은 2014 년 8 월에 중단되었습니다.
Glavić

2
이 날짜를 고려하십시오var_dump( validateDate('2012-2-9'));
15:59

4
기능이 올바르게 작동합니다. 지정한 thr 형식이 올바르지 않아서 false를 리턴했습니다. 선행 0없이 일과 월을 사용하려면 형식은 'Y-n-j'@reignsly 여야합니다.
Amal Murali 2016 년

1
@ AntonyD'Andrea : 아니요, 해당 부분이 없으면 작동하지 않습니다. 때문에 $d거짓되지 않습니다 당신은 그것을 13 월 (2013-13-01)처럼 오버 플로워 부분이 날짜를 제공합니다. 그러나 그것은 실제로 당신이 원하는 것에 달려 있습니다. 예 validateDate('2015-55-66')를 들어 유효 해야하는 경우 예, $d객체인지 여부 만 확인하면됩니다 .
Glavić

81

문자열이 날짜인지 확인

function checkIsAValidDate($myDateString){
    return (bool)strtotime($myDateString);
}

2
이것은뿐만 아니라 모든 유효한 날짜 형식을 검증합니다 yyyy-mm-dd.
EWit

10
@MichelAyres 이것은 2015-02-30주어진 날짜가 주어진 달 (또는 음수)의 PHP가 다음 달로 롤오버 되기 때문에 php가 유효한 날짜로 간주 하기 때문입니다. 날짜는 형식 yyyy-mm-dd이어야하므로 반환 값을로 변경하여 수정할 수 있습니다 return (bool)strtotime($myDateString) && date("Y-m-d", strtotime($myDateString)) == $myDateString;.
elitechief21

2
(bool)strtotime('s')사실로 나오나요?
Peon

또한 1 checkIsAValidDate ( "F");
Vaibhav Bhanushali

우리가 사용할 수있는 $myDateString = str_replace("/", '-', $myDateString);일 / 월 / 년 - : 날짜 문자열이 같은 슬래시 (/)를 포함하는 경우 반환하기 전에
Yashrajsinh Jadeja을

37

PHP 사전 빌드 기능으로 간단한 방법으로 사용하십시오.

function checkmydate($date) {
  $tempDate = explode('-', $date);
  // checkdate(month, day, year)
  return checkdate($tempDate[1], $tempDate[2], $tempDate[0]);
}

테스트

   checkmydate('2015-12-01'); //true
   checkmydate('2015-14-04'); //false

1
좋은 솔직한 솔루션, 처음으로 작업, 감사 :)
David Bell

테스트를 사용할 때 다시, 내부 if단순히 반환 true하거나 false, 시험 자체를 반환합니다.
Victor Schröder

4
$ tempDate 배열에 3 개 이상의 요소가 있다고 가정합니다.
person27

2
@ person27 :return sizeof($tmpDate) == 3 && checkdate($tmpDate[1]...
neurino 2016 년

@vineet-실패합니다. 올해 인 경우 2, 20, 202, 2020올해는 심지어 경우 20201- 그것은 때마다 true를 돌려줍니다.
rolinger

16

문자열이 비표준 형식 인 경우에도 문자열이 날짜인지 확인

(strtotime은 사용자 정의 형식을 허용하지 않습니다)

<?php
function validateDateTime($dateStr, $format)
{
    date_default_timezone_set('UTC');
    $date = DateTime::createFromFormat($format, $dateStr);
    return $date && ($date->format($format) === $dateStr);
}

// These return true
validateDateTime('2001-03-10 17:16:18', 'Y-m-d H:i:s');
validateDateTime('2001-03-10', 'Y-m-d');
validateDateTime('2001', 'Y');
validateDateTime('Mon', 'D');
validateDateTime('March 10, 2001, 5:16 pm', 'F j, Y, g:i a');
validateDateTime('March 10, 2001, 5:16 pm', 'F j, Y, g:i a');
validateDateTime('03.10.01', 'm.d.y');
validateDateTime('10, 3, 2001', 'j, n, Y');
validateDateTime('20010310', 'Ymd');
validateDateTime('05-16-18, 10-03-01', 'h-i-s, j-m-y');
validateDateTime('Monday 8th of August 2005 03:12:46 PM', 'l jS \of F Y h:i:s A');
validateDateTime('Wed, 25 Sep 2013 15:28:57', 'D, d M Y H:i:s');
validateDateTime('17:03:18 is the time', 'H:m:s \i\s \t\h\e \t\i\m\e');
validateDateTime('17:16:18', 'H:i:s');

// These return false
validateDateTime('2001-03-10 17:16:18', 'Y-m-D H:i:s');
validateDateTime('2001', 'm');
validateDateTime('Mon', 'D-m-y');
validateDateTime('Mon', 'D-m-y');
validateDateTime('2001-13-04', 'Y-m-d');

테스트를 사용하는 경우, 내부 if단순히 반환 true하거나 false, 시험 자체를 반환합니다.
Victor Schröder

그러나 2018-3-24는 false를 반환하고, 메서드는 2018-3-24를 받고, 형식이 적용되면 2018-03-24를 반환합니다. 어떻게 두 가지 방법으로 사실을 반환 할 수 있습니까?
Aquiles Perez

12

이 옵션은 단순 할뿐만 아니라 거의 모든 형식을 허용하지만 비표준 형식의 경우 버그가있을 수 있습니다.

$timestamp = strtotime($date);
return $timestamp ? $date : null;

이것은 받아 들여진 대답이어야합니다! 훨씬 더 간단합니다.
웹 마스터 G

2
영국식 (d / m / Y) 형식에서는 미국식 (m / d / Y)을 변환한다고 가정하므로이 기능은 작동하지 않습니다. 하루가 12보다 낮은 경우에만 작동하는 것 같습니다!
실베스터 사라 세 바스

@galki-이것을 테스트했는데 특정 값이 실패합니다. $ date = '202-03-31'이면 true를 반환합니다. 그러나 그것은 유효한 날짜가 아닙니다. 연도를 유효하지 않은 연도로 변경하면 항상 true를 반환한다는 것을 알았습니다.
rolinger

@rolinger 이상한 ... 아마도 202AD를보고 있습니까? 'strtotime'은 몇 년의 타임 스탬프를 제공합니까?
galki

@galki-확실하지 않지만 202음수를 반환하여 여전히 테스트를 통과합니다.
rolinger

10

월 날짜와 연도의 날짜를 구문 분석 한 다음 checkdate()여기에서 읽을 수 있는 PHP 함수 를 사용할 수 있습니다. http://php.net/manual/en/function.checkdate.php

당신은 또한 이것을 시도 할 수 있습니다 :

$date="2013-13-01";

if (preg_match("/^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])$/",$date))
    {
        echo 'Date is valid';
    }else{
        echo 'Date is invalid';
    }

2 월의 경우 (elitechief21에 의해 언급 된) 함수 isValidDate ($ date) {return preg_match ( "/ ^ [0-9] {4}-(0 [1-9] | 1 [0-2])-(0 [1-9] | [1-2] [0-9] | 3 [0-1]) $ / ", $ date) && date ("Ymd ", strtotime ($ date)) == $ date; }
abdulwadood

4
이 솔루션은 날짜 유효성을 어떤 의미로도 확인하지 않기 때문에 매우 열악합니다. 2 월을 포함하여 모든 달에는 31 일이있을 수 있습니다. 모든 연도는 2 월 29 일입니다. RegExp를 사용하여 날짜를 확인하려면 역 참조 및 부정적인 미리보기로 훨씬 복잡한 것이 필요합니다.
Victor Schröder

9

주어진 날짜가 유효한지 확인하는 가장 쉬운 방법은를 사용하여 날짜를 unixtime으로 변환 strtotime하고 주어진 날짜 형식으로 형식을 지정한 다음 비교합니다.

function isValidDate($date) { return date('Y-m-d', strtotime($date)) === $date; }

물론 정규식을 사용하여 유효성을 검사 할 수 있지만 다른 형식을 만족시키기 위해 편집해야 할 때마다 지정된 형식으로 제한되며 필요한 것 이상이됩니다. 내장 기능은 작업을 수행하는 가장 좋은 방법입니다 (대부분의 경우).


1
나는 이미 strtotime 답변 이 있다는 것을 고려할 때이 답변의 품질이 매우 낮다고 생각 합니다.
GrumpyCrouton

4
이것은 가장 짧은 대답이며 작동합니다. 품질이 낮다고 말하는 것은 조금 거칠다.
Tim Rogers

@ user4600953-이것이 가장 쉬운 방법입니다. 다른 사람들이 많이 사용한다고 checkdate()말하지만 올해가 모든 값이면 검사 날짜가 실패합니다 2, 20, 202, 2020, 20201.-모두 true를 반환합니다. 나는 당신의 해결책으로 가고 있습니다!
rolinger

7

cl-sah의 답변과 일치하지만이 소리는 더 좋고 짧습니다 ...

function checkmydate($date) {
  $tempDate = explode('-', $date);
  return checkdate($tempDate[1], $tempDate[2], $tempDate[0]);
}

테스트

checkmydate('2015-12-01');//true
checkmydate('2015-14-04');//false

count($tempDate) === 3그래도 테스트해야합니다
VDarricau

그들이없는 경우 @VDarricau없이 당신이 checkdate은 폭탄 것입니다하지 않습니다, 당신은 모든 하나 하나에 대해 ()는 isset 쓸 수 있지만 단순히 경고를 억제 것
씨 Heelis

7

PHP를 사용해도 기능적인 솔루션 을 찾는 것이 좋습니다. 예를 들어 @migli의 대답은 실제로 매우 유연하고 우아합니다.

그러나 문제가 있습니다. 같은 형식의 많은 DateTime 문자열을 검증해야하는 경우 어떻게해야합니까? DRY 원칙에 어긋나는 방식으로 모든 곳에서 형식을 반복해야 할 것 입니다. 우리는 형식을 상수로 넣을 수는 있지만 여전히 모든 함수 호출에 대한 상수로 상수를 전달해야합니다.

그러나 더 이상 두려워하지 마십시오! 우리는 구조에 카레 를 사용할 수 있습니다 ! PHP는이 작업을 즐겁게하지는 않지만 PHP로 카레를 구현할 수 있습니다.

<?php
function validateDateTime($format)
{
    return function($dateStr) use ($format) {
        $date = DateTime::createFromFormat($format, $dateStr);
        return $date && $date->format($format) === $dateStr;
    };
}

그래서 우리가 방금 한 일은? 기본적으로 함수 본문을 익명으로 감싸고 대신 해당 함수를 반환했습니다. 다음과 같이 유효성 검사 기능을 호출 할 수 있습니다.

validateDateTime('Y-m-d H:i:s')('2017-02-06 17:07:11'); // true

네, 큰 차이는 아니지만 ... 진정한 힘은 부분적으로 적용되는 기능 에서 비롯됩니다 .

// Get a partially applied function
$validate = validateDateTime('Y-m-d H:i:s');

// Now you can use it everywhere, without repeating the format!
$validate('2017-02-06 17:09:31'); // true
$validate('1999-03-31 07:07:07'); // true
$validate('13-2-4 3:2:45'); // false

기능 프로그래밍 FTW!


2
산사태 IMHO의 가장 좋은 답변 (다른 답변과 동일한 유연성과 더 많은 양의 코드로 OP의 특정 문제를 해결 함)
StubbornShowaGuy

IMHO 이것은 정말 못생긴 프로그래밍입니다. 값을 배열에 넣고 루프를 통과하여 유효성을 검사하지만이를 수행하지 마십시오!
Tim

@Tim이 궁금합니다. 어레이 / 루프 유효성 검사의 예를 들어 주시겠습니까?
Victor Schröder

5

대부분의 투표 솔루션 ( https://stackoverflow.com/a/19271434/3283279 )이 제대로 작동하지 않을까 걱정 됩니다. 네 번째 테스트 사례 (var_dump (validateDate ( '2012-2-25') ;; // false))가 잘못되었습니다. 날짜는 형식에 해당하기 때문에 정확합니다. m앞에 0 이 있거나없는 허용 합니다 ( http://php.net/manual/en/datetime.createfromformat.php 참조 ). 따라서 날짜 2012-2-25Ymd 형식 이며 테스트 케이스는 false가 아닌 true 여야합니다.

더 나은 해결책은 다음과 같이 가능한 오류를 테스트하는 것입니다.

function validateDate($date, $format = 'Y-m-d') {
    DateTime::createFromFormat($format, $date);
    $errors = DateTime::getLastErrors();

    return $errors['warning_count'] === 0 && $errors['error_count'] === 0;
}

3

이건 어때?

우리는 단순히 try-catch 블록을 사용합니다.

$dateTime = 'an invalid datetime';

try {
    $dateTimeObject = new DateTime($dateTime);
} catch (Exception $exc) {
    echo 'Do something with an invalid DateTime';
}

이 방법은 하나의 날짜 / 시간 형식으로 만 제한되지 않으며 함수를 정의 할 필요가 없습니다.


이 0000-00-00 0시 0분 0초 날짜 값에 대해 작동하지 않습니다
Naseeruddin VN에게

@NaseeruddinVN '0000-00-00 00:00:00'은 유효한 날짜 시간 값입니다. 첫 번째 값일뿐입니다. 그러나 datetime 객체의 date 속성은입니다 '-0001-11-30 00:00:00'.
율리우스

1

테스트 된 정규식 솔루션 :

    function isValidDate($date)
    {
            if (preg_match("/^(((((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])))))$/", $date)) {
                    return $date;
            }
            return null;
    }

날짜가 유효하지 않거나 yyyy-mm-dd 형식이 아닌 경우 null을 반환하고 그렇지 않으면 날짜를 반환합니다.



0
/*********************************************************************************
Returns TRUE if the input parameter is a valid date string in "YYYY-MM-DD" format (aka "MySQL date format")
The date separator can be only the '-' character.
*********************************************************************************/
function isMysqlDate($yyyymmdd)
{
    return checkdate(substr($yyyymmdd, 5, 2), substr($yyyymmdd, 8), substr($yyyymmdd, 0, 4)) 
        && (substr($yyyymmdd, 4, 1) === '-') 
        && (substr($yyyymmdd, 7, 1) === '-');
}

-1
    /**** date check is a recursive function. it's need 3 argument 
    MONTH,DAY,YEAR. ******/

    $always_valid_date = $this->date_check($month,$day,$year);

    private function date_check($month,$day,$year){

        /** checkdate() is a php function that check a date is valid 
        or not. if valid date it's return true else false.   **/

        $status = checkdate($month,$day,$year);

        if($status == true){

            $always_valid_date = $year . '-' . $month . '-' . $day;

            return $always_valid_date;

        }else{
            $day = ($day - 1);

            /**recursive call**/

            return $this->date_check($month,$day,$year);
        }

    }

1
설명이없는 코드는별로 유용하지 않습니다.
Gert Arnold

-2

이것을 시도하십시오 :

$date = "2017-10-01";


function date_checker($input,$devider){
  $output = false;

  $input = explode($devider, $input);
  $year = $input[0];
  $month = $input[1];
  $day = $input[2];

  if (is_numeric($year) && is_numeric($month) && is_numeric($day)) {
    if (strlen($year) == 4 && strlen($month) == 2 && strlen($day) == 2) {
      $output = true;
    }
  }
  return $output;
}

if (date_checker($date, '-')) {
  echo "The function is working";
}else {
  echo "The function isNOT working";
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.