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

全栈打杂
• 阅读 833

一、概念

讨论在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"));
    }
}

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

五、使用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模式

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

下面是直接使用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));

七、总结

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

点赞
收藏
评论区
推荐文章
Karen110 Karen110
4年前
一篇文章带你了解JavaScript日期
日期对象允许您使用日期(年、月、日、小时、分钟、秒和毫秒)。一、JavaScript的日期格式一个JavaScript日期可以写为一个字符串:ThuFeb02201909:59:51GMT0800(中国标准时间)或者是一个数字:1486000791164写数字的日期,指定的毫秒数自1970年1月1日00:00:00到现在。1\.显示日期使用
皕杰报表(关于日期时间时分秒显示不出来)
在使用皕杰报表设计器时,数据据里面是日期型,但当你web预览时候,发现有日期时间类型的数据时分秒显示不出来,只有年月日能显示出来,时分秒显示为0:00:00。1.可以使用tochar解决,数据集用selecttochar(flowdate,"yyyyMMddHH:mm:ss")fromtablename2.也可以把数据库日期类型date改成timestamp
Wesley13 Wesley13
4年前
java8 时间类与Date类的相互转化
java8时间类与Date类的相互转化在转换中,我们需要注意,因为java8之前Date是包含日期和时间的,而LocalDate只包含日期,LocalTime只包含时间,所以与Date在互转中,势必会丢失日期或者时间,或者会使用起始时间。如果转LocalDateTime,那么就不存在信息误差。//Date与Instant的相互转化
Wesley13 Wesley13
4年前
Java8 日期、时间操作
<divid"cnblogs\_post\_body"class"blogpostbody"<p一、简介</p<p  在Java8之前,日期时间API一直被开发者诟病,包括:java.util.Date是可变类型,SimpleDateFormat非线程安全等问题。故此,Java8引入了一套全新的日期时间处理API,新的API基于ISO标准
Wesley13 Wesley13
4年前
Java 8中处理日期和时间示例
在Java8以前,日期和时间处理一直被广大java程序员抱怨太难用,首先是java.util和java.sql中,都包含Date类,如果要处理java.text.DateFormat类处理。同时java.util.Date中既包含了日期,又包含了时间,所以java8新的日期和时间库,很好的解决了以前日期和时间类的很多弊端。并且也借鉴了第
Stella981 Stella981
4年前
JS 苹果手机日期显示NaN问题
问题描述newDate("2019122910:30:00")在IOS下显示为NaN原因分析带的日期IOS下存在兼容问题解决方法字符串替换letdateStr"2019122910:30:00";datedateStr.repl
Wesley13 Wesley13
4年前
Java8 必会的日期处理的实践,必须收藏!
编辑:业余草来源:https://www.xttblog.com/?p4944Java8日期处理Java8推出了全新的日期时间API,在教程中我们将通过一些简单的实例来学习如何使用新API。Java处理日期、日历
Wesley13 Wesley13
4年前
Java 8 时间日期库的20个使用演示样例
除了lambda表达式,stream以及几个小的改进之外,Java8还引入了一套全新的时间日期API,在本篇教程中我们将通过几个简单的任务演示样例来学习怎样使用Java8的这套API。Java对日期,日历及时间的处理一直以来都饱受诟病。尤其是它决定将java.util.Date定义为可改动的以及将SimpleDateFormat实现成非线程安全的。看
Wesley13 Wesley13
4年前
Java8中计算日期时间差
一.简述在Java8中,我们可以使用以下类来计算日期时间差异:1.Period2.Duration3.ChronoUnit二.Period类主要是Period类方法getYears(),getMonths()和getDays()来计算.示例:
Stella981 Stella981
4年前
LocalDateTime用法(jdk1.8 )
前言最近看别人项目源码,发现Java8新的日期时间API很方便强大,所以转载该入门介绍博客,记录一下。使用新时间日期API的必要性在java8以前,或许:当你在做有关时间日期的操作时,你会想到用Date;当你在做日期、月份、天数相加减时,你会想到用Calendar;当你需要对时间日期进行格式化时
小万哥 小万哥
2年前
SQL 日期处理和视图创建:常见数据类型、示例查询和防范 SQL 注入方法
SQL处理日期在数据库操作中,处理日期是一个关键的方面。确保插入的日期格式与数据库中日期列的格式匹配至关重要。以下是一些常见的SQL日期数据类型和处理方法。SQL日期数据类型MySQL日期数据类型DATE格式为YYYYMMDDDATETIME格式为YYYY
全栈打杂
全栈打杂
Lv1
所有的快乐,都来源于生活的心动。
文章
4
粉丝
0
获赞
0