最近要写校验身份证号的代码。这个东西用 AI 都能帮我自动生成了。 但是 AI 生成的代码里没有检查出生日期部分的代码。如果不检查,仅对校验和做检查, 那么形如下面的“身份证号”就会通过检查:
123456789012345677
123456202502305672
这肯定是不行的。我得自己补一个出生日期检查。
检查日期的代码当然也是 AI 来写。核心逻辑如下:
private static final DateTimeFormatter DF = DateTimeFormatter.ofPattern("yyyyMMdd");
public static boolean checkDate(String date) {
try {
LocalDate.parse(date, DF);
return true;
} catch (Exception e) {
return false;
}
}
这段代码写完后,我们发现对于 20250230
这样的日期,居然检查不出来!
于是我在 jshell 里试验了一下:
jshell> import java.time.format.DateTimeFormatter
jshell> var df = DateTimeFormatter.ofPattern("yyyyMMdd")
df ==> Value(YearOfEra,4,19,EXCEEDS_PAD)Value(MonthOfYear,2)Value(DayOfMonth,2)
jshell> df.parse("20250230")
$3 ==> {},ISO resolved to 2025-02-28
jshell> df.parse("20250231")
$4 ==> {},ISO resolved to 2025-02-28
jshell> df.parse("20250232")
| 异常错误 java.time.format.DateTimeParseException:Text '20250232' could not be parsed: Invalid value for DayOfMonth (valid values 1 - 28/31): 32
| at DateTimeFormatter.createError (DateTimeFormatter.java:2079)
| at DateTimeFormatter.parse (DateTimeFormatter.java:1940)
| at (#5:1)
| 原因: java.time.DateTimeException: Invalid value for DayOfMonth (valid values 1 - 28/31): 32
可以看到,Java 解析日期偷了懒,没有判断闰年,甚至没有按大月小月做区分,
只是简单粗暴的设定了一个 31 日的上限,在 31 之内,它会“智能”调整日期到合适的值。
比如,把 20250231
调成了 20250228
。
这就是前大语言模型时代的“人工”智能?
这套日期时间 API 是 Java 8 引入的,我测试使用的是 Java 21。显然,这特么是个 feature!!
最朴素的想法,就是自己写一个:
可是这么一搞的话,代码就长了。写这么一大段代码肯定耽误下班。我们得换个写法。
下面就是新写法,不解释了,一看就懂:
private static final DateTimeFormatter DF = DateTimeFormatter.ofPattern("yyyyMMdd");
public static boolean checkDate(String date) {
try {
return LocalDate.parse(date, DF).format(DF).equals(date);
} catch (Exception e) {
return false;
}
}