PHP正则expression式检查date是YYYY-MM-DD格式
我试图检查最终用户input的date是在YYYY-MM-DD。 正则expression式从来没有是我的强项,我一直得到preg_match()我已经设置一个虚假的返回值。
所以我假设我已经弄乱了正则expression式,详见下文。
$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; }
这可能是更好的使用另一种机制。
现代的解决scheme,与DateTime
:
$dt = DateTime::createFromFormat("Ymd", $date); return $dt !== false && !array_sum($dt->getLastErrors());
这也validation了input: $dt !== false
确保date可以用指定的格式进行parsing,而array_sum
技巧是确保PHP不会执行“月份移动”的简单方法(例如,考虑1月32日是2月1)。 有关更多信息,请参阅DateTime::getLastErrors()
。
带explode
和检查的老式解决scheme:
list($y, $m, $d) = array_pad(explode('-', $date, 3), 3, 0); return ctype_digit("$y$m$d") && checkdate($m, $d, $y);
这也validationinput是有效的date。 你当然可以用正则expression式来做,但是会更加大惊小怪,而且2月29日也不能用正则expression式来validation。
这种方法的缺点是,在任何情况下,您都必须非常小心地拒绝所有可能的“坏”input,而不发出通知。 就是这样:
-
explode
限于返回3个令牌(所以如果input是“1-2-3-4”,$d
将变成“3-4”) -
ctype_digit
用于确保input不包含任何非数字字符(除了破折号) -
array_pad
(带有会导致checkdate
失败的默认值),以确保返回了足够的元素,这样如果input是“1-2”,list()
将不会发出通知
标准:
每一年除以四是一个闰年,除非它可以被100整除,除非它可以被400整除。所以:
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
二月有闰年29天,闰年不过28天
4月,6月,9月和11月30天
1月,3月,5月,7月,8月,10月和12月31天
testing:
以下date都应通过validation:
1976-02-29 2000-02-29 2004-02-29 1999-01-31
以下date应该都不通过validation:
2015-02-29 2015-04-31 1900-02-29 1999-01-32 2015-02-00
范围:
我们将testing从1000年1月1日到2999年12月31日的date。从技术上讲,目前使用的公历只是在1753年为大英帝国使用,并在17世纪在欧洲各国的不同年份,但我不打算担心这一点。
正则expression式来testing闰年:
可以被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)
不包括二月份的有效月份和date(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)
有效date:
(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月31date间,您可以使用YYYY-MM-DD格式的正则expression式。
我怀疑它可以缩短很多,但我会把它留给其他人。
这将匹配所有有效的date。 如果你只希望它只包含一个date而没有其他的东西,那么把它包装在^( )$
就像这样:
^(((((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条目(即它可以是空白或有效的date),然后添加^$|
在开始时,像这样:
^$|^(((((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: /^((((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
/^(((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
/^(((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
/^(((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
你可以这样做:
if (preg_match("/\d{4}\-\d{2}-\d{2}/", $date)) { echo 'true'; } else { echo 'false'; }
但是你最好使用这个:
$date = DateTime::createFromFormat('Ym-d', $date); if ($date) { echo $date -> format('Ym-d'); }
在这种情况下,你会得到一个比string更容易使用的对象。
您可以使用checkg_match和checkdate php函数
$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;
preg_match需要一个/或另一个字符作为分隔符。
preg_match("/^[0-9]{4}-[0-1][0-9]-[0-3][0-9]$/",$date)
你也应该检查该date的有效性,所以你不会像9999-19-38那样结束
bool checkdate ( int $month , int $day , int $year )
我知道这是一个老问题。 但是我觉得我有一个很好的解决scheme。
$date = "2016-02-21"; $format = "Ymd"; if(date($format, strtotime($date)) == date($date)) { echo "true"; } else { echo "false"; }
你可以尝试一下。 如果将date更改为21.02.2016,则回显为false。 如果你将格式改为dmY,则回显为真。
有了这个简单的代码,你应该能够检查使用哪种date格式,而不用正则expression式检查。
也许有一个人会对每一个案子进行testing。 但我认为我的想法一般是有效的。 对我来说这似乎合乎逻辑。
如果您想匹配该types的date,请使用:
preg_match("~^\d{4}-\d{2}-\d{2}$~", $date)
这应该告诉你,如果格式是有效的,如果inputdate是有效的。
$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'; }
这完全取决于你想要这个function有多严格。 例如,如果你不想让12个月以上的月份和31天以上的日子(不依赖于月份,这将需要写date逻辑),它可能会变得非常复杂:
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})$/
要在PHP中使用date,你应该遵循PHP标准,所以给定的正则expression式将确保你有有效的date,可以使用PHP操作。
preg_match("/^([0-9]{4})-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])$/",$date)
这个方法可以用来在PHP中validationdate。 当前的方法是以mm / dd / yyyy格式。 您必须根据您的格式和爆炸中的分隔符更新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; } }