正则表达式验证yyyy/mm/dd格式日期失效,请求技术解析
Hey there! Let's break down why your regex isn't working as expected, especially since your example valid date 2016/05/12 is failing. First, I notice a potential contradiction in your requirements: you said the month's first digit must be 1 or 2, but your example uses 05 (first digit 0) as a valid date. That's probably where the confusion starts!
常见的正则错误点
Let's go through the most likely issues with your regex:
1. 月份规则的正则写错了
If you wrote something like [12]\d for the month part, that would only match months from 10 to 29 — which excludes valid single-digit months like 01-09 (and even though 10-12 would match, 05 would fail outright). This directly explains why your example 2016/05/12 is being rejected.
2. 没有正确处理边界或分隔符
- Forgetting to add start (
^) and end ($) anchors means your regex might match partial strings (likeabc2016/05/12defwould incorrectly pass as valid). - If you accidentally used the wrong separator (like
-instead of/) or escaped/unnecessarily (in regex flavors where it's not required), that would break valid matches.
3. 日期部分的校验缺失或过度严格
Even if you fix the month, a too-loose date regex (like \d{2}) would allow invalid dates like 32, while an overly strict one might reject valid dates without accounting for month-specific day ranges. This is a secondary issue, but it can still cause unexpected failures.
修复后的正则 & 代码示例
Assuming your actual requirement is to validate valid Gregorian dates in yyyy/mm/dd format (since your example uses 05 as a valid month), here's a corrected approach:
First, a regex that handles the format correctly (we'll handle logical validity like leap years in code, since regex can't fully handle that complexity):
^\d{4}/(0[1-9]|1[012])/(0[1-9]|[12]\d|3[01])$
Let's break this down:
^\d{4}: Starts with exactly 4 digits for the year/(0[1-9]|1[012])/: Month part, matches 01-09 (single-digit months with leading zero) or 10-12(0[1-9]|[12]\d|3[01])$: Date part, matches 01-09, 10-29, or 30-31, and ends the string to prevent partial matches
Here's a Java code example that uses this regex, throws your InvalidDateException, and adds logical date validation:
import java.time.LocalDate; import java.time.format.DateTimeFormatter; import java.time.format.DateTimeParseException; public class DateValidator { private static final String DATE_REGEX = "^\\d{4}/(0[1-9]|1[012])/(0[1-9]|[12]\\d|3[01])$"; private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy/MM/dd"); public static void validateDate(String dateStr) throws InvalidDateException { // First check format with regex if (!dateStr.matches(DATE_REGEX)) { throw new InvalidDateException("Invalid format: must be yyyy/mm/dd with valid month/day ranges"); } // Validate logical date validity (leap years, month-specific days) try { LocalDate.parse(dateStr, FORMATTER); } catch (DateTimeParseException e) { throw new InvalidDateException("Logically invalid date: " + e.getMessage()); } } // Example usage public static void main(String[] args) { try { validateDate("2016/05/12"); // Valid, should pass System.out.println("Date is valid!"); } catch (InvalidDateException e) { System.out.println(e.getMessage()); } try { validateDate("2016/13/12"); // Invalid month, throws exception } catch (InvalidDateException e) { System.out.println(e.getMessage()); } try { validateDate("2023/02/29"); // Invalid leap year date, throws exception } catch (InvalidDateException e) { System.out.println(e.getMessage()); } } } // Your existing InvalidDateException class class InvalidDateException extends Exception { public InvalidDateException(String message) { super(message); } }
如果确实需要严格按你写的规则(月份首位为1或2)
If you really meant that the month's first digit must be 1 or 2 (so months 10-29), then the regex for the month part would be [12]\d — but your example 2016/05/12 would be invalid. In that case, your regex was probably correct, but your example doesn't align with your stated requirements.
内容的提问来源于stack exchange,提问作者Schnitzel




