关于java:Java中检查字符串是否是有效日期

一、概念

探讨在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));

七、总结

本文总结了验证字符串是否蕴含无效日期的几种办法。

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理