Java Instant.parse 无法验证日期

Java Instant.parse cannot validate date

我有一个即时字段并尝试使用以下方法验证该字段中的值:

Instant.parse("2021-09-29 09:35:07.531")

但是,它抛出错误:

java.time.format.DateTimeParseException: Text '2021-09-29 09:35:07.531' could not be parsed at index 10.

那么,我如何测试字符串格式的给定 Instant 日期是否是有效的 Instant 日期?

我正在实施导入功能,我需要检查日期单元格。因此,日期通常以即时格式保存在数据库中,因此我需要检查单元格日期值是否是有效的即时日期。所以,如果有更合适的方法,我当然可以照着做。

我不使用该值,我只需要检查日期是否是有效日期。

如果您尝试使用 Instant class,则必须参考时区。那么,让我们试试这个:

LocalDateTime.from(DateTimeFormatter.ofPattern("yyyy-MM-dd H:mm:ss.SSS").parse("2021-09-29 09:35:07.351")).atZone(ZoneId.systemDefault()).toInstant();

您的日期时间字符串没有时区信息,因此您无法在不引入时区的情况下将其解析为 Instant。我建议您将其解析为 LocalDateTime,如果它应该独立于时区使用,则将其用于数据库工作。

演示:

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.Locale;

public class Main {
    public static void main(String args[]) {
        DateTimeFormatter dtfInput = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss.SSS", Locale.ENGLISH);
        LocalDateTime ldt = LocalDateTime.parse("2021-09-29 09:35:07.531", dtfInput);
        System.out.println(ldt);
    }
}

输出:

2021-09-29T09:35:07.531

ONLINE DEMO

如何在JDBC中使用LocalDateTime

下面给出了将 LocalDateTime 插入 columnfooTIMESTAMP 类型)的示例代码:

PreparedStatement st = conn.prepareStatement("INSERT INTO mytable (columnfoo) VALUES (?)");
st.setObject(1, ldt);
st.executeUpdate();
st.close();

下面给出了从 columnfoo 检索 LocalDateTime 的示例代码:

Statement st = conn.createStatement();
ResultSet rs = st.executeQuery("SELECT * FROM mytable WHERE <some condition>");
while (rs.next()) {
    // Assuming the column index of columnfoo is 1
    LocalDateTime ldt = rs.getObject(1, LocalDateTime.class));
    System.out.println(ldt);
}
rs.close();
st.close();

如果您想将给定的日期时间字符串解析为 Instant:

如上所述,您需要引入时区才能将其解析为Instant

演示:

import java.time.Instant;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Locale;

public class Main {
    public static void main(String args[]) {
        // Change the ZoneId to the applicable one e.g. ZoneId.of("Etc/UTC")
        DateTimeFormatter dtfInput = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss.SSS", Locale.ENGLISH)
                                        .withZone(ZoneId.systemDefault());

        Instant instant = Instant.from(dtfInput.parse("2021-09-29 09:35:07.531"));
        System.out.println(instant);
    }
}

在我的时区输出,Europe/London:

2021-09-29T08:35:07.531Z

ONLINE DEMO

了解有关 modern Date-Time API* from Trail: Date Time 的更多信息。


* 如果您正在为一个 Android 项目工作并且您的 Android API 级别仍然不符合 Java-8,请检查Java 8+ APIs available through desugaring. Note that Android 8.0 Oreo already provides support for java.time

So, how can I test if the given Instant date in String format is a valid Instant date?

不是。

瞬间是一个(唯一的)时间点。您的字符串包含一天中的日期和时间。在不知道时区的情况下,这可能表示 24 或 27 小时范围内的某个时间点——与一个时间点相去甚远。

编辑:我了解到您正在从某处导入字符串,您无法决定字符串的格式或内容,您需要对其进行验证。您可以将其验证为日期和时间。您基本上不能将其转换为 Instant,或者至少您只能在我不知道其有效性的假设下进行转换。为了进行验证,我建议使用此格式化程序:

private static final DateTimeFormatter PARSER = new DateTimeFormatterBuilder()
        .append(DateTimeFormatter.ISO_LOCAL_DATE)
        .appendLiteral(' ')
        .append(DateTimeFormatter.ISO_LOCAL_TIME)
        .toFormatter(Locale.ROOT);

格式化程序重用内置格式化程序并接受可变的秒数小数,我认为这在许多情况下都有意义。你更清楚它是否适用于你。

这样验证:

    String importedDateTimeString = "2021-09-29 09:35:07.531";
    try {
        LocalDateTime.parse(importedDateTimeString, PARSER);
        System.out.format("Valid date and time: %s%n", importedDateTimeString);
    } catch (DateTimeParseException dtpe) {
        System.out.format("Not a valid date and time: %s. Validation error: %s%n",
                importedDateTimeString, dtpe);
    }

输出:

Valid date and time: 2021-09-29 09:35:07.531

原始建议:因此请改用包含与 UTC 的偏移量的格式。特别是在 UTC 中的 ISO 8601 格式是出于多种目的的推荐选项,例如 2021-09-29T01:35:07.531Z.

Link: Wikipedia article: ISO 8601