Java强校验日期格式

SimpleDateFormat

// lenient默认为true,即为宽松模式,如需严格校验,则需设置lenient为false
String date = "2021/02/29";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
sdf.setLenient(false);
// 抛错
sdf.parse(date);

DateTimeFormatter

// ResolverStyle默认为SMART,即以聪明的方式解决日期和时间,如需严格校验,设置为STRICT,另外还存在LENIENT宽松模式
String date = "2021/02/29";
DateTimeFormatter df = DateTimeFormatter.ofPattern("uuuu/MM/dd", Locale.getDefault()).withResolverStyle(ResolverStyle.STRICT);
// 抛错
LocalDate.parse(date, df);

在STRICT严格模式下,需注意

在Javadoc节模式用于格式化和解析为DateTimeFormatter它列出了以下3个相关的符号:

Symbol  Meaning        Presentation  Examples
------  -------        ------------  -------
 G       era            text          AD; Anno Domini; A
 u       year           year          2004; 04
 y       year-of-era    year          2004; 04
仅作比较,这些其他符号很容易理解:

 D       day-of-year    number        189
 d       day-of-month   number        10
 E       day-of-week    text          Tue; Tuesday; T
的day-of-year,day-of-month和day-of-week显然是当天在给定范围(年,月,周)内.

因此,year-of-era表示给定范围(时代)内的年份,并且正上方era显示的是示例值AD(当然是其他值BC).

year是签署的年份,年份0是1 BC,年份-1是2 BC等等.

举例说明:朱利叶斯凯撒何时被暗杀?
	公元前44年3月15日(使用模式MMMM d, y GG)
	3月15日-43(使用模式MMMM d, u)
	
当然,区别仅在于年份是零还是负面,而且由于这种情况很少见,大多数人都不关心,即使他们应该这样做.

结论:如果你使用y你也应该使用G.由于G很少使用,因此正确的年份符号u不是y,否则非正年将显示不正确.

这被称为防御性编程:

防御性编程是一种防御性设计,旨在确保在不可预见的情况下软件的持续功能.

注意DateTimeFormatter与SimpleDateFormat以下内容一致:

Letter  Date or Time Component  Presentation  Examples
------  ----------------------  ------------  --------
G       Era designator          Text          AD
y       Year                    Year          1996; 96
负面年份一直是一个问题,他们现在通过添加修复它u.