一、概念
探讨在Java中查看一个字符串是否蕴含无效日期的各种办法,包含Java8之前与Java8之后及Apache Commons Validator的解决方案。
二、日期概述
不论是应该还是办法,在接收数据时,咱们都必须在解决之前验证它的有效性。
在输出日期的状况下咱们须要验证上面几点:
- 输出蕴含无效的日期格局,如MM/DD/YYYY
- 输出的各个局部都在无效范畴内
- 能够解析为日历中的无效日期
咱们能够用正则表达式来实现上述工作,然而正则在解决各种输出格局时很简单且容易出错,并且还会升高性能。
上面探讨各种灵便、稳键、高效的日期验证的办法。
首先咱们编写一个日期验证的接口。
public interface DateValidator { boolean isValid(String dateStr);}
上面就以不同的办法来实现这个接口。
三、应用DateFormat
Java从一开始就提供了格式化和解析日期的工具。这些性能在抽像类DateFormat和它的实现类SimpleDateFormat中。
让咱们应用DateFormat来实现日期验证吧。
public class DateValidatorUsingDateFormat implements DateValidator { private String dateFormat; public DateValidatorUsingDateFormat(String dateFormat) { this.dateFormat = dateFormat; } @Override public boolean isValid(String dateStr) { DateFormat sdf = new SimpleDateFormat(this.dateFormat); // 应用严格的解析 sdf.setLenient(false); try { sdf.parse(dateStr); } catch (ParseException e) { return false; } return true; }}
因为DateFormat相干类是线程不平安,咱们须要为每个办法调用创立一个新的实例。上面咱们就来写单元测试:
public class DateValidatorUsingDateFormatUnitTest { @Test public void givenValidator_whenValidDatePassed_ThenTrue() { DateValidator validator = new DateValidatorUsingDateFormat("MM/dd/yyyy"); assertTrue(validator.isValid("02/28/2019")); } @Test public void givenValidator_whenInvalidDatePassed_ThenFalse() { DateValidator validator = new DateValidatorUsingDateFormat("MM/dd/yyyy"); assertFalse(validator.isValid("02/30/2019")); }}
这是Java 8之前的通常的解决方案。
四、应用LocalDate
Java 8引入了改良的日期和工夫API。增加了LocalDate类,只示意日期。这个类是线程平安的。
LocalDate提供了两个表态办法来解析日期,都应用DateTimeFormatter来解析:
public static LocalDate parse(CharSequence text)// parses dates using using DateTimeFormatter.ISO_LOCAL_DATEpublic static LocalDate parse(CharSequence text, DateTimeFormatter formatter)// parses dates using the provided formatter
上面用这个解析办法来实现日期验证
public class DateValidatorUsingLocalDate implements DateValidator { private DateTimeFormatter dateFormatter; public DateValidatorUsingLocalDate(DateTimeFormatter dateFormatter) { this.dateFormatter = dateFormatter; } @Override public boolean isValid(String dateStr) { try { LocalDate.parse(dateStr, this.dateFormatter); } catch (DateTimeParseException e) { return false; } return true; }}
上面写单元测试
public class DateValidatorUsingLocalDateUnitTest { DateTimeFormatter dateFormatter = DateTimeFormatter.BASIC_ISO_DATE; DateValidator validator = new DateValidatorUsingLocalDate(dateFormatter); @Test public void givenValidator_whenValidDatePassed_ThenTrue() { assertTrue(validator.isValid("20190228")); } @Test public void givenValidator_whenInValidDatePassed_ThenFalse() { assertFalse(validator.isValid("20190230")); }}
五、应用DateTimeFormater
上一节中LocalDate应用DateTimeFormatter对象进行解析,咱们也能够间接应用DateTimeFormatter类进行格式化解析。
DateTimeFormatter分两个阶段解析文本。阶段1,它依据配置将日期字符串解析为日期和工夫字段。阶段2,它将这些日期和工夫字段解析为对象。ResolverStyle管制阶段2,它有3个值:
// 论断// ResolverStyle formatter.parse(text) LocalDate.parse(text, formatter)// ------------- --------------------- ---------------------------------// STRICT 6.31,6.32不合理输入 6.31,6.32抛异样// SMART 6.31按6.30算 6.32抛异样 同左// LENIENT 往后延6.31按7.1算 6.32按7.2算 同左// DateTimeFormatter.ofPatter("yyyy-MM-dd") 是ResolverStyle.SMART模式
上面是间接应用DateTimeFormatter编写日期验证:
public class DateValidatorUsingDateTimeFormatter implements DateValidator { private DateTimeFormatter dateFormatter; public DateValidatorUsingDateTimeFormatter(DateTimeFormatter dateFormatter) { this.dateFormatter = dateFormatter; } @Override public boolean isValid(String dateStr) { try { this.dateFormatter.parse(dateStr); } catch (DateTimeParseException e) { return false; } return true; }}
写测试
public class DateValidatorUsingDateTimeFormatterUnitTest { @Test public void givenValidator_whenValidDatePassed_ThenTrue() { DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd", Locale.SIMPLIFIED_CHINESE) .withResolverStyle(ResolverStyle.STRICT); DateValidator validator = new DateValidatorUsingDateTimeFormatter(dateFormatter); assertTrue(validator.isValid("2019-02-28")); } @Test public void givenValidator_whenInValidDatePassed_ThenFalse() { DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd", Locale.SIMPLIFIED_CHINESE) .withResolverStyle(ResolverStyle.STRICT); DateValidator validator = new DateValidatorUsingDateTimeFormatter(dateFormatter); assertFalse(validator.isValid("2019-02-30")); }}
六、应用Apache Commons Validator
Apache Commons我的项目提供了一个验证框架,能够验证日期、工夫、数字、货币、IP、Email和URL。
本文次要看GenericValidator类,它提供了几种办法来验证String是否蕴含无效日期:
public static boolean isDate(String value, Locale locale) public static boolean isDate(String value,String datePattern, boolean strict)
要应用这个库先增加依赖
<dependency> <groupId>commons-validator</groupId> <artifactId>commons-validator</artifactId> <version>1.6</version></dependency>
用GenericValidator类来实现日期验证
assertTrue(GenericValidator.isDate("2019-02-28", "yyyy-MM-dd", true));assertFalse(GenericValidator.isDate("2019-02-29", "yyyy-MM-dd", true));
七、总结
本文总结了验证字符串是否蕴含无效日期的几种办法。