PHP 7.4如何强制校验严格匹配ddmmYYYY格式的日期输入
严格校验固定长度ddmmYYYY格式日期的实现方案
DateTime::createFromFormat('dmY', 日期字符串) 本身不做输入长度强校验,遇到长度不符合的字符串时会按规则自动截取解析:例如传入长度为6的212022时,方法会自动取前两位21作为日期、中间两位20作为月份、最后两位22补全为2022年作为年份,不会返回false,最终生成错误的解析结果,无法拦截不符合格式的输入。
要实现严格的2位日期+2位月份+4位年份的固定8位格式校验,可以通过三层校验组合实现:
- 第一层:固定长度校验。直接判断输入字符串长度必须严格等于8,长度不符直接判定为非法,优先过滤掉少位、多位的错误输入。
- 第二层:正则格式前置校验。通过正则匹配输入必须为纯数字,且日、月的取值符合基础范围规则,提前过滤掉明显不符合格式的输入。如果需要限制年份范围,可以自行调整正则中的年份匹配规则。
- 第三层:日期真实性校验。调用
DateTime::createFromFormat解析日期后,将解析结果按dmY格式反向格式化输出,比对输出结果是否和原始输入完全一致,拦截正则无法识别的、实际不存在的日期(比如2月31日、4月31日这类存在数值溢出的非法日期)。
完整校验代码示例:
function isStrictValidDdmmYyyy(string $input): bool { // 校验长度必须为8位 if (strlen($input) !== 8) { return false; } // 正则校验基础格式:日01-31、月01-12、4位年份 if (!preg_match('/^(0[1-9]|[12][0-9]|3[01])(0[1-9]|1[012])(\d{4})$/', $input)) { return false; } // 解析后反向比对,拦截溢出的非法日期 $dateObj = DateTime::createFromFormat('dmY', $input); return $dateObj && $dateObj->format('dmY') === $input; } // 测试结果 var_dump(isStrictValidDdmmYyyy('14012022')); // 输出bool(true),符合格式的合法日期 var_dump(isStrictValidDdmmYyyy('212022')); // 输出bool(false),长度不足直接拦截 var_dump(isStrictValidDdmmYyyy('02012022')); // 输出bool(true),正确的2022年1月2日 var_dump(isStrictValidDdmmYyyy('31022022')); // 输出bool(false),2月不存在31日 var_dump(isStrictValidDdmmYyyy('31042022')); // 输出bool(false),4月只有30天,存在日期溢出 var_dump(isStrictValidDdmmYyyy('14132022')); // 输出bool(false),月份13超出合法范围
注意:反向格式化比对是必不可少的环节,PHP的DateTime解析默认存在自动溢出修正逻辑,例如传入
31042022时,方法不会返回false,而是会自动将日期修正为5月1日,只有通过反向比对格式化后的字符串和原始输入是否一致,才能识别这类非法输入。
内容的提问来源于stack exchange,提问作者naspy971
相关产品推荐
相关产品推荐

