我正在尝试检查最终用户输入的日期是否在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;
}
if (DateTime::createFromFormat('Y-m-d', $date)->format('Y-m-d') === $date) {
// date is correctly formatted and valid, execute some code
}
日期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
}
中的格式和定界符更新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');
中的参数序列。为此最好使用其他机制。
现代解决方案,带有DateTime
:
DateTime
这也验证了输入:$dt = DateTime::createFromFormat("Y-m-d", $date);
return $dt !== false && !array_sum($dt::getLastErrors());
确保可以使用指定的格式解析日期,并且$dt !== false
技巧是确保PHP不进行“月度移位”的简洁方法(例如,考虑1月32日为2月1日)。有关更多信息,请参见array_sum
。
DateTime::getLastErrors()
和DateTime::getLastErrors()
的旧式解:
explode
这也验证了输入也是一个有效日期。您当然可以使用正则表达式来做到这一点,但这会大惊小怪-2月29日根本无法使用正则表达式进行验证。
这种方法的缺点是,您必须非常小心地拒绝所有可能的“不良”输入,而在任何情况下都不会发出通知。方法如下:
explode
仅限返回3个令牌(因此,如果输入为“ 1-2-3-4”,则checkdate
将变为“ 3-4”)]checkdate
用于确保输入不包含任何非数字字符(破折号除外)explode
失败的默认值)以确保返回了足够的元素,以便如果输入为“ 1-2”,则$d
将不会发出通知格式1:$ format1 =“ 2012-12-31”;
yyyy-mm-dd:ctype_digit
yyyy / mm / dd:
array_pad
mm-dd-yyyy:
checkdate
mm / dd / yyyy:
list()
dd / mm / yyyy:
/^((((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
dd-mm-yyyy:
/^((((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
标准:
每年被4整除的年份是a年,除非它可以被100整除,除非可以被400整除。因此:/^(((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
2月Fe年有29天,非not年有28天以下日期均应通过验证:4月,6月,9月和11月的30天
[一月,三月,五月,七月,八月,十月和十二月的31天
测试:
/^(((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
以下日期均应通过验证:
/^(((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
我们将测试1000年1月1日至2999年12月31日之间的日期。范围:
技术上,目前使用的公历仅在1753年用于大英帝国,并在1600年代分别用于欧洲国家,但我我不会为此担心。
正则表达式测试test年:
可被400整除的年份:/^(((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整除:
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
年份可被100整除:
1976-02-29 2000-02-29 2004-02-29 1999-01-31
不可被100整除:
2015-02-29 2015-04-31 1900-02-29 1999-01-32 2015-02-00
年份可被100整除而不是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,但不能除以100:
[12]\d([02468][048]|[13579][26])
The年:
[12]\d00
无法被4整除:
[12]\d([1-9]\d|\d[1-9])
不是a年:
((1[1345789])|(2[1235679]))00
有效月份和月份,不包括二月(MM-DD):
[12]\d([2468][048]|[13579][26]|0[48])
[2月28天:
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])
2月,共29天:
[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)
因此,您拥有一个正则表达式,用于YYYY-MM-DD格式的1000年1月1日至2999年12月31日之间的日期。我怀疑它可以缩短很多,但我会把它留给别人。
将匹配所有有效日期。如果您只希望它仅包含一个日期而没有其他任何内容时才有效,则将其包装在
((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))
中,如下所示:
02-(0[1-9]|1\d|2[0-8])
如果要在可选日期输入中输入它(例如,可以为空白或有效日期),请在开头添加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]))))