解析 ISO_INSTANT 和类似的日期时间字符串

Parsing ISO_INSTANT and similar Date Time Strings

我昨天创建了这个很棒的静态方法,它工作得很好 - 昨天

但是,今天它给了我这个错误。我猜是因为 Z 之前的 0 太多了。

任何人都可以推荐如何以简洁的方式解析 (Java 8) 这种类型的 String 格式日期 - 请记住它昨天也有效,所以 ISO_INSTANT 是也是 String?

的有效格式
Caused by: java.time.DateTimeException: Unable to obtain LocalDate from TemporalAccessor: {NanoOfSecond=0, InstantSeconds=1443451604, MilliOfSecond=0, MicroOfSecond=0},ISO of type java.time.format.Parsed
at java.time.LocalDate.from(LocalDate.java:368)
at java.time.LocalDateTime.from(LocalDateTime.java:456)
... 9 more

输入时间抛出异常:“2015-09-28T14:46:44.000000Z”

/**
 *
 * @param time the time in RFC3339 format (e.g. "2013-07-03T14:30:38Z" )
 * @return
 */
public static LocalDateTime parseTimeINSTANT(String time) {
    DateTimeFormatter f = DateTimeFormatter.ISO_INSTANT;
    return LocalDateTime.from(f.parse(time));
}

您正在解析与 ISO 即时一致的字符串,因此您需要将结果存储在 Instant 而不是 LocalDateTime:

public static Instant parseTimeINSTANT(String time) {
    DateTimeFormatter f = DateTimeFormatter.ISO_INSTANT;
    return Instant.from(f.parse(time)); // could be written f.parse(time, Instant::from);
}

请注意,此格式化程序可以正确处理小数秒,因此您无需删除它们。引用 DateTimeFormatter.ISO_INSTANT Javadoc(强调我的):

When parsing, time to at least the seconds field is required. Fractional seconds from zero to nine are parsed.

至于为什么它昨天有效而今天无效,我不知道...

只是为了帮助以后看到这个问题的人。

您需要将 ISO 日期解析为 Instant,将其转换为 Instant 对象,然后从中创建一个 LocalDateTime,提供区域 ID。我在这里设置 UTC 的区域 ID。

代码如下

public static LocalDateTime getISODate(String dateString) {
    DateTimeFormatter isoFormatter = DateTimeFormatter.ISO_INSTANT;
    Instant dateInstant = Instant.from(isoFormatter.parse(dateString));
    LocalDateTime date = LocalDateTime.ofInstant(dateInstant, ZoneId.of(ZoneOffset.UTC.getId()));

    return date;
}

ISO_INSTANT 没有区域信息。只需添加即可。 或者使用 DateTimeFormatter.ISO_ZONED_DATE_TIME 代替

import java.time.*;
import java.time.format.*;

public class TestMain {

    DateTimeFormatter formatter = DateTimeFormatter.ISO_INSTANT.withZone(ZoneId.of("Z"));

    DateTimeFormatter formatter2 = DateTimeFormatter.ISO_ZONED_DATE_TIME

    public static void main(String[] args) {
        ZonedDateTime.parse("2031-12-01T10:58:30Z", formatter);
        ZonedDateTime.parse("2031-12-01T10:58:30Z", formatter2);
    }
}

你不需要 DateTimeFormatter

使用 Instant#parse. The modern Date-Time API is based on ISO 8601 将符合 ISO 8601 的日期时间字符串直接解析为 Instant,并且不需要明确使用 DateTimeFormatter 对象,只要日期时间字符串符合符合 ISO 8601 标准。

演示:

import java.time.Instant;

public class Main {
    public static void main(String[] args) {
        Instant instant = Instant.parse("2015-09-28T14:46:44.000000Z");
        System.out.println(instant);
    }
}

输出:

2015-09-28T14:46:44Z

ONLINE DEMO

如果我想要 UTC 的 LocalDateTime 怎么办?

Instant 可以转换为其他 java.time 类型,例如

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneOffset;

public class Main {
    public static void main(String[] args) {
        Instant instant = Instant.parse("2015-09-28T14:46:44.000000Z");
        System.out.println(instant);

        LocalDateTime ldt = instant.atZone(ZoneOffset.UTC).toLocalDateTime();
        System.out.println(ldt);
    }
}

输出:

2015-09-28T14:46:44Z
2015-09-28T14:46:44

ONLINE DEMO

Trail: Date Time.

了解有关现代日期时间 API 的更多信息