# Java – 日期验证

> 原文： [https://howtodoinjava.com/java/date-time/date-validation/](https://howtodoinjava.com/java/date-time/date-validation/)

学习验证给定的字符串是否包含日期值。 我们将学习 Java 7， [Java 8](https://howtodoinjava.com/java-8-tutorial/) 及更高版本中可用的各种**日期验证**技术。

## 1\. `DateTimeFormatter` – Java 8

*   最好的机会是您的应用程序已经在使用 Java 8 或更高版本。 在这种情况下，用 Java 表示日期的最佳方法是使用[`LocalDate`](https://howtodoinjava.com/java/date-time/java-time-localdate-class/)类。
*   默认情况下，`LocalDate.parse()`方法使用`ISO_LOCAL_DATE`模式（`yyyy-MM-dd`）解析日期。 格式包括：
    *   年份的四位数或更多，其中 0000 到 9999 的范围将被补零，以确保四位数。 超出该范围的年份将带有前缀正号或负号。
    *   一年中的两位数字，并用零预填充以确保两位数字。
    *   每月中的两位数字，并用零预填充以确保两位数字。
*   如果我们有自己的自定义日期格式，则可以使用`DateTimeFormatter.ofPattern()`方法创建。 默认情况下，`ResolverStyle.SMART`用于每个日期字段使用明智的默认值。 例如，“天”字段的值大于 31 将是有效值，并将其视为月份的最后一天。
*   很多时候，这种智能解决方案无法满足业务需求，如果遇到此类无效值，我们希望引发解析异常。 使用`ResolverStyle.STRICT`严格解析日期和时间。 使用严格的分辨率将确保所有解析的值都在该字段的有效值的外部范围内。
*   使用`LocalDate`的`parse(dateString, dateTimeFormatter)`将字符串解析为`Localdate`实例。
*   [`DateTimeFormatter`](https://howtodoinjava.com/java/date-time/java8-datetimeformatter-example/)实例是线程安全且不可变的，因此我们只能为每个模式/应用程序创建一个实例，并在其他函数之间共享它。

```java
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.time.format.ResolverStyle;

public class JavaDateValidations 
{
	public static void main(String[] args) 
	{
		String dateFormat = "MM-dd-yyyy";
		String dateString = "05-26-2020";

		DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern(dateFormat)
											.withResolverStyle(ResolverStyle.STRICT);

		LocalDate parsedLocalDate = validateAndParseDateJava8(dateString, dateFormatter);

		System.out.println(parsedLocalDate);
	}

	//Java 8 - Use DateTimeFormatter (thread-safe)
	public static LocalDate validateAndParseDateJava8(String dateStr, DateTimeFormatter dateFormatter) 
	{
		LocalDate date = null;
        try {
        	date = LocalDate.parse(dateStr, dateFormatter);
        } catch (DateTimeParseException e) {
        	e.printStackTrace();
        }
        return date;
    }
}

```

## 2\. `SimpleDateFormat` – Java 7

*   如果您仍然对 Java 7 感到震惊，并且由于某些旧应用程序的依赖性而无法升级，则可以使用`SimpleDateFormat`进行日期验证。
*   尽管`SimpleDateFormat`不是线程安全的或不可变的，但它仍然可以很好地达到目的。 不要在具有同步功能的多线程环境中使用此类。
*   不要忘记使用[`setLenient()`](https://howtodoinjava.com/java/date-time/strict-date-validation-simpledateformat-setlenient/)方法来指定宽大因素。 使用宽大的解析，解析器可能会使用启发式方法来解释与该对象的格式不完全匹配的输入。 在严格分析的情况下，输入内容必须与此对象的格式匹配。
*   然后，使用`SimpleDateFormat`的`parse(dateString)`方法，该方法将引发受检的异常`ParseException`，该异常表示将日期字符串解析为`java.util.Date`对象时发生了一些错误。

```java
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class JavaDateValidations 
{
	public static void main(String[] args) 
	{
		String dateFormat = "MM-dd-yyyy";
		String dateString = "05-26-2020";

		Date parsedDate = validateAndParseDateJava7(dateString, dateFormat);

		System.out.println(parsedDate);
	}

	//Java 7 - Use SimpleDateFormat (not thread-safe)
	public static Date validateAndParseDateJava7(String dateString, String dateFormat) {
		Date date = null;
        DateFormat sdf = new SimpleDateFormat(dateFormat);
        sdf.setLenient(false);
        try {
            date = sdf.parse(dateString);
        } catch (ParseException e) {
        	e.printStackTrace();
        }
        return date;
    }
}

```

## 3\. 日期验证的最佳做法

以下是一些在 Java 中验证日期期间可以遵循的最佳实践。

1.  尽管在 99% 的情况下不会有任何区别，但仍然可以考虑使用`'uuuu'`代替`'yyyy'`。 有关更多信息，请参考此 [SO 帖子](https://stackoverflow.com/questions/41177442/uuuu-versus-yyyy-in-datetimeformatter-formatting-pattern-codes-in-java)。
2.  使用相关方法（即`sdf.setLenient(false)`或`dtf.withResolverStyle(ResolverStyle.STRICT)`）使用严格的解析。
3.  尽管严格的日期解析解决了大多数问题，但仍应考虑使用额外的检查 -- 例如，有效的解析日期必须在预定义的日期范围内。 批量分析对日期敏感的记录时，这可能非常有用。 例如，我们可以从大型 Excel 工作表中导入财务记录时使用这种类型的验证，因为手工工作出错的可能性很高。
4.  如果您有将 Java 7 应用程序升级到 Java 8 的自由，请优先执行。 就性能而言，`DateTimeFormatter`的线程安全性和不变性是对`SimpleDateFormat`的巨大胜利。

在评论中给我您有关在 Java 中将字符串解析为日期对象的问题和建议。

学习愉快！

[下载源码](https://github.com/lokeshgupta1981/Core-Java/tree/master/src/com/howtodoinjava/core/datetime)