在 java 中验证 ISO8601 日期时间字符串的推荐方法是什么

Whats the recommended way to validate ISO8601 datetime string in java

我正在使用 java11。想知道什么是最好的(最重要的是推荐)验证日期时间字符串是否符合 [=18] 中的 ISO8601 标准的方法=].

还有如何将此字符串值与 java.sql.Timestamp 进行比较?

假设您至少使用 Java 8 最简单的方法是这样的:

private static boolean isIsoDate(String date) {
    try {
        Instant.from(DateTimeFormatter.ISO_INSTANT.parse(date));
        return true;
    } catch (DateTimeParseException e) {
        //log the failure here
        e.printStackTrace();
    }
    return false;
}

相反,您可以使用 regex 验证格式,但这比上述方法更难。

至于您的其他问题,最简单的方法是先将您的日期字符串转换为具体的 Date 对象,然后按照此处的建议操作:

Compare Date object with a TimeStamp in Java

form java 8以后可以用DateTimeFormatter class来检查格式,所以我定义了一个方法来检查它是否在ISO格式与否:

boolean isValidISODateTime(String date) {
    try {
        java.time.format.DateTimeFormatter.ISO_DATE_TIME.parse(date);
        return true;
    } catch (java.time.format.DateTimeParseException e) {
        return false;
    }
}

ISO 8601 太多了,所以我不打算写一个详尽的答案。我试图概述您可能会选择的选项。之后你应该进一步研究相关的one/s。也许在这样做之前,您需要研究什么是 ISO 8601,它有时是什么,什么不是。

出于许多(大多数)目的,尝试使用 java.time 的内置方法解析您的字符串,现代 Java 日期和时间 API,会给您一个满意的验证,如其他答案中所述。选项是:

  • 更简单且最常用:使用来自 java.time 的适当日期时间 class 的单参数 parse 方法。他们通常解析 ISO 8601 格式并在字符串不是 ISO 8601 格式时抛出 DateTimeParseException。根据您的字符串中需要显示的信息(日期 and/or 时间,UTC 偏移量),例如,您可以使用 OffsetDateTime.parse()LocalDate.parse().
  • 对于特殊或异国情调的需求,请使用 DateTimeFormatter class 的 ISO_XXXX 常量之一。

以上至少有三种方法对您来说可能不够:

  1. 提到的内置方法解析并接受最常见的 ISO 8601 变体。例如,OffsetDateTime.parse(CharSequence) 需要在与 UTC 的偏移量中有一个冒号(如果它不是 Z),如 +07:00。 ISO 8601 还允许不带冒号写入偏移量,如 +0700。如果您需要适应内置方法未涵盖的变体,构建您自己的 DateTimeFormatter 可能是一个不错且不太复杂的解决方案。您可以使用 DateTimeForamtter.ofPattern 方法或 DateTimeFormatterBuilder.
  2. 内置方式有时会允许您可能不想允许的值。例如,在严格的 ISO 8601 中,一年介于 1583 和 9999 之间(含)。 java.time 的 classes 允许从 -999 999 999 到 +999 999 999 的年份。您的解决方案是在解析后进行范围检查。日期时间 classes 有方法 isBeforeisAfter 为此。
  3. ISO 8601 包括 时间间隔,java.time 不提供 class 或格式化程序,包括重复时间间隔。如果你想允许这些,你可能会寻找不同的日期和时间库(想到 Time4J 和 ThreeTen Extra)或者你将不得不自己做更多的工作来验证。

如何与 java.sql.Timestamp 进行比较?

如果可以避免使用 java.sql.Timestamp, do. That class is poorly designed and long outdated. Since JDBC 4.2 we prefer fetching timestamps as OffsetDateTime or LocalDateTime from our SQL 数据库。

如果您从遗留的 API 中获得了 Timestamp,而您现在无力升级,请将每个都转换为 Instant and compare them using isBefore() or isAfter()。这是一个例子:

    String yourIso8601String = "2020-11-17T02:51:39.375109+07:00";
    Timestamp ts = Timestamp.from(Instant.parse("2020-11-16T19:00:00Z"));
    
    OffsetDateTime odt = OffsetDateTime.parse(yourIso8601String);
    boolean isBeforeTimestamp = odt.toInstant().isBefore(ts.toInstant());
    System.out.println("Is the ISO 8601 string before the Timestamp? " + isBeforeTimestamp);

示例的输出是:

Is the ISO 8601 string before the Timestamp? false

链接