최종 사용자가 입력 한 날짜가 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()
.
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 일은 정규식으로 전혀 유효성을 검사 할 수 없습니다.
이 접근 방식의 단점은 어떤 상황에서도 알림을 표시하지 않고 가능한 모든 “나쁜”입력을 거부하도록 매우주의해야한다는 것입니다. 방법은 다음과 같습니다.
explode
3 개의 토큰을 반환하도록 제한됩니다 (입력이 “1-2-3-4″인$d
경우 “3-4″가 됨).ctype_digit
입력에 숫자가 아닌 문자 (대시 제외)가 포함되지 않았는지 확인하는 데 사용됩니다.array_pad
checkdate
입력이 “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');
}
이 경우 문자열보다 사용하기 더 쉬운 객체를 얻을 수 있습니다.
답변
나는 이것이 오래된 질문이라는 것을 알고 있습니다. 하지만 좋은 해결책이 있다고 생각합니다.
$date = "2016-02-21";
$format = "Y-m-d";
if(date($format, strtotime($date)) == date($date)) {
echo "true";
} else {
echo "false";
}
시도해 볼 수 있습니다. 날짜를 21.02.2016으로 변경하면 에코가 거짓입니다. 그 후 형식을 dmY로 변경하면 에코가 참입니다.
이 쉬운 코드를 사용하면 정규식에서 확인하지 않고도 사용되는 날짜 형식을 확인할 수 있습니다.
모든 경우에 테스트 할 사람이있을 수 있습니다. 하지만 내 생각은 일반적으로 유효하다고 생각합니다. 나에게는 논리적으로 보인다.
답변
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;