PHP如何验证日期为d/m/Y格式,排除m/d/Y格式?
解决PHP验证d/m/Y日期格式的问题
你的问题核心在于两个点:一是原函数会因为格式化后补零导致和原输入不匹配,二是宽松的日期解析会把无效月份(比如20)自动转换,导致误判。下面给你两种可行的解决方案:
方案一:改进DateTime解析逻辑(推荐)
这个方案保留了DateTime的日期有效性验证,同时解决了前导零和宽松解析的问题:
function validateDateFormats(string $date, string $format = 'd/m/Y') { // 开启严格解析模式,遇到无效日期直接返回false $d = DateTime::createFromFormat($format . '|', $date); if (!$d) { return false; } // 拆分输入的日、月、年,去掉前导零后和解析结果对比 list($inputDay, $inputMonth, $inputYear) = explode('/', $date); return (int)$d->format('d') === (int)$inputDay && (int)$d->format('m') === (int)$inputMonth && $d->format('Y') === $inputYear; } // 测试用例 var_dump(validateDateFormats('20/4/1999')); // bool(true) var_dump(validateDateFormats('20/04/1999')); // bool(true) var_dump(validateDateFormats('4/20/1999')); // bool(false) var_dump(validateDateFormats('04/20/1999')); // bool(false)
关键说明:
- 在格式字符串末尾加
|是开启严格解析模式,这样如果输入的月份是20这种无效值,createFromFormat会直接返回false,不会自动转换日期。 - 我们没有直接对比格式化后的字符串和原输入,而是把输入的日、月转成整数后和解析结果的日、月(转整数)对比,这样不管输入是一位还是两位数字,只要数值正确就会通过验证。
方案二:正则匹配+checkdate验证
如果你更倾向于手动控制格式验证,可以用正则先匹配格式,再用checkdate验证日期有效性:
function validateDateFormats(string $date) { // 匹配日(1-2位)/月(1-2位)/年(4位)的格式 if (!preg_match('/^(\d{1,2})\/(\d{1,2})\/(\d{4})$/', $date, $matches)) { return false; } $day = (int)$matches[1]; $month = (int)$matches[2]; $year = (int)$matches[3]; // 先检查月份是否在1-12之间 if ($month < 1 || $month > 12) { return false; } // 用checkdate验证日期的有效性(自动处理闰年、不同月份的天数差异) return checkdate($month, $day, $year); } // 测试用例 var_dump(validateDateFormats('20/4/1999')); // bool(true) var_dump(validateDateFormats('20/04/1999')); // bool(true) var_dump(validateDateFormats('4/20/1999')); // bool(false) var_dump(validateDateFormats('04/20/1999')); // bool(false)
关键说明:
- 正则确保了输入的格式是
日/月/年的结构,避免了月/日/年的混淆。 checkdate是PHP内置函数,能准确验证日期的有效性,比如2月29日只在闰年返回true,4月没有31日等。
这两个方案都能满足你的需求,你可以根据自己的代码风格选择其中一种。
内容的提问来源于stack exchange,提问作者fractal5
相关产品推荐
相关产品推荐

