1. 概述

在 Java 开发中,我们经常需要判断一个字符串是否表示一个合法日期。比如在解析用户输入、处理日志文件或接口参数校验时,这种需求非常常见。

本文将介绍几种常见的方法来验证字符串是否为有效日期:

  • 使用 DateFormat(适用于 Java 8 之前)
  • 使用 LocalDate(Java 8 及以上)
  • 使用 DateTimeFormatter
  • 使用 Apache Commons Validator

2. 日期校验的基本需求

在实际开发中,我们验证日期字符串通常需要满足以下几点:

✅ 字符串格式符合预期(如 MM/dd/yyyy
✅ 各字段数值在合法范围内(如月份 1~12)
✅ 组合后确实是一个合法的日期(如 2023-02-29 是不合法的)

虽然可以用正则表达式进行格式校验,但正则难以处理复杂的格式和本地化问题,容易出错且性能较差。

因此,我们更推荐使用 Java 内置的日期 API 或第三方库进行验证。

我们先定义一个通用的接口:

public interface DateValidator {
    boolean isValid(String dateStr);
}

接下来分别实现这个接口。

3. 使用 DateFormat 校验(适用于 Java 8 之前)

SimpleDateFormat 是 Java 早期版本中常用的日期格式化类。我们可以通过其 parse() 方法来判断字符串是否能被正确解析。

示例实现如下:

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;
    }
}

⚠️ 注意:SimpleDateFormat 不是线程安全的,每次调用都创建新实例。

测试用例:

DateValidator validator = new DateValidatorUsingDateFormat("MM/dd/yyyy");

assertTrue(validator.isValid("02/28/2019"));        
assertFalse(validator.isValid("02/30/2019"));

这是 Java 8 之前最常见的做法。

4. 使用 LocalDate 校验(Java 8+)

Java 8 引入了全新的 java.time 包,其中 LocalDate 是一个不可变、线程安全的日期类。

我们可以通过 LocalDate.parse() 方法结合 DateTimeFormatter 来校验日期字符串:

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;
    }
}

测试示例:

DateTimeFormatter dateFormatter = DateTimeFormatter.BASIC_ISO_DATE;
DateValidator validator = new DateValidatorUsingLocalDate(dateFormatter);

assertTrue(validator.isValid("20190228"));
assertFalse(validator.isValid("20190230"));

✅ 优点:线程安全,API 更现代,推荐使用。

5. 使用 DateTimeFormatter 校验

DateTimeFormatter 不仅用于格式化,也可以单独用于解析日期字符串。它支持设置解析策略(ResolverStyle),控制解析的严格程度。

支持的解析策略有:

  • LENIENT:宽松模式
  • SMART:智能解析(默认)
  • STRICT:严格模式

示例实现如下:

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;
    }
}

测试示例:

DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("uuuu-MM-dd", Locale.US)
    .withResolverStyle(ResolverStyle.STRICT);
DateValidator validator = new DateValidatorUsingDateTimeFormatter(dateFormatter);

assertTrue(validator.isValid("2019-02-28"));
assertFalse(validator.isValid("2019-02-30"));

⚠️ 注意:DateTimeFormatterparse() 方法只解析字段,不会自动验证是否构成合法日期。所以建议结合 LocalDate.parse() 使用更稳妥。

6. 使用 Apache Commons Validator

如果你的项目已经引入了 Apache Commons 系列库,可以考虑使用 commons-validator 中的 GenericValidator 类。

使用方式如下:

assertTrue(GenericValidator.isDate("2019-02-28", "yyyy-MM-dd", true));
assertFalse(GenericValidator.isDate("2019-02-29", "yyyy-MM-dd", true));

需要添加 Maven 依赖:

<dependency>
    <groupId>commons-validator</groupId>
    <artifactId>commons-validator</artifactId>
    <version>1.6</version>
</dependency>

✅ 优点:简单易用,适合已有 Apache Commons 依赖的项目
❌ 缺点:功能较基础,灵活性不如 Java 8 的 java.time API

7. 总结

方法 适用版本 线程安全 推荐程度
SimpleDateFormat Java 8 前 ⚠️ 已过时,仅兼容旧代码
LocalDate Java 8+ ✅ 推荐
DateTimeFormatter Java 8+ ✅ 推荐(结合 LocalDate
Apache Commons Validator 所有 ⚠️ 适合已有依赖项目

最佳实践建议:优先使用 Java 8 的 LocalDate.parse() + DateTimeFormatter,简洁、线程安全、功能强大。

完整示例代码可参考 GitHub 仓库


原始标题:Check If a String Is a Valid Date in Java

« 上一篇: Java Weekly, 第288期