写点什么

Java 中检查字符串是否是有效日期

作者:okokabcd
  • 2022 年 6 月 15 日
  • 本文字数:3084 字

    阅读完需:约 10 分钟

一、概念

讨论在 Java 中检查一个字符串是否包含有效日期的各种方法,包括 Java8 之前与 Java8 之后及 Apache Commons Validator 的解决方案。

二、日期概述

不管是应该还是方法,在接收数据时,我们都必须在处理之前验证它的有效性。在输入日期的情况下我们需要验证下面几点:


  1. 输入包含有效的日期格式,如 MM/DD/YYYY

  2. 输入的各个部分都在有效范围内

  3. 可以解析为日历中的有效日期


我们可以用正则表达式来完成上述工作,但是正则在处理各种输入格式时很复杂且容易出错,并且还会降低性能。下面讨论各种灵活、稳键、高效的日期验证的方法。首先我们编写一个日期验证的接口。


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_DATE
public 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));
复制代码

七、总结

本文总结了验证字符串是否包含有效日期的几种方法。

发布于: 刚刚阅读数: 3
用户头像

okokabcd

关注

还未添加个人签名 2019.11.15 加入

一年当十年用的Java程序员

评论

发布
暂无评论
Java中检查字符串是否是有效日期_Java_okokabcd_InfoQ写作社区