如何从模式创建Java时间瞬间?

Che*_*rry 32 java java-time

考虑一下代码:

TemporalAccessor date = DateTimeFormatter.ofPattern("yyyy-MM-dd").parse("9999-12-31");
Instant.from(date);
Run Code Online (Sandbox Code Playgroud)

最后一行抛出异常:

Unable to obtain Instant from TemporalAccessor: {},ISO resolved to 9999-12-31 of type java.time.format.Parsed
Run Code Online (Sandbox Code Playgroud)

如何Instantyyyy-MM-dd模式创建?

Jod*_*hen 52

字符串"9999-12-31"仅包含有关日期的信息.它不包含有关时间或偏移的任何信息.因此,没有足够的信息来创建Instant.(其他日期和时间库更宽松,但java.time避免默认这些值)

你的第一选择是用一个LocalDate而不是一个'瞬间:

LocalDate date = LocalDate.parse("9999-12-31");
Run Code Online (Sandbox Code Playgroud)

你的第二个选择是发布处理日期以将其转换为瞬间,这需要一个时区,这里选择巴黎:

LocalDate date = LocalDate.parse("9999-12-31");
Instant instant = date.atStartOfDay(ZoneId.of("Europe/Paris")).toInstant();
Run Code Online (Sandbox Code Playgroud)

您的第三个选择是将时区添加到格式化程序,并默认为时间:

static final DateTimeFormatter FMT = new DateTimeFormatterBuilder()
    .appendPattern("yyyy-MM-dd")
    .parseDefaulting(ChronoField.NANO_OF_DAY, 0)
    .toFormatter()
    .withZone(ZoneId.of("Europe/Paris"));
Instant instant = FMT.parse("9999-31-12", Instant::from);
Run Code Online (Sandbox Code Playgroud)

(如果这不起作用,请确保您拥有最新的JDK 8版本,因为此区域中已修复了错误).

值得注意的是,这些可能性都不TemporalAccessor直接使用,因为该类型是低级框架接口,而不是大多数应用程序开发人员使用的接口.

  • 与你所展示的[`parse`](https://docs.oracle.com/javase/8/docs/api/java/time/Instant.html#parse-java.lang.CharSequence-)方法相反`java.util.Instant`没有`DateTimeFormatter`.相反,你必须做`FMT.parse("9999-31-12",Instant :: from)`.正如作者可以解释为什么`Instant`与其他类不同,例如`LocalDateTime`,在这方面? (3认同)

Han*_*k D 19

问题不在于您使用的是9999年.该Instant.MAX字段的计算结果为时间戳1000000000-12-31T23:59:59.999999999Z,因此一年中9999就可以了.

与处理TemporalAccessors,而不是像更语义丰富的类型LocalDateTime或者ZonedDateTime是像使用Map一个对象及其属性模特,而不是写一个class-你必须确保该值的字段(例如秒,纳秒等),由被预期接收它的东西,而不是依赖于更高级别类中的正式声明的操作来防止依赖性未被满足.

在您的情况下,时间访问器可能包含已分配的日期字段,但没有Instant所需的"秒"字段.LocalDateTime在大多数情况下,最好使用语义更丰富的类型.

由于您只有日期字段,因此应将其解析为日期,然后在将其转换为Instant之前添加时间字段.这是一种方法,使用LocalDate来解析日期:

LocalDate localDate = LocalDate.parse("2016-04-17");
LocalDateTime localDateTime = localDate.atStartOfDay();
Instant instant = localDateTime.toInstant(ZoneOffset.UTC);
Run Code Online (Sandbox Code Playgroud)


Abh*_*hek 6

public static void main(String[] args) throws ParseException {
        System.out.println(new SimpleDateFormat("yyyy-MM-dd").parse("2016-12-31").toInstant());
}
Run Code Online (Sandbox Code Playgroud)

上面的代码给出以下输出:

2016-12-31T00:00:00Z

我已经使用Java 8的features('toInstant'方法)回答了这个问题,希望这可以回答您的问题...

  • 该代码可任意设置许多内容(并将旧的Date API与新的Java time API混合在一起)... (3认同)
  • 我认为投票否定的原因是我上面所说的:(i)您不必要地混用了API,这很令人困惑;(ii)示例的输出取决于用户时区(如果您在夏威夷,它将打印例如“ 2016-12-31T10:00:00Z”)。 (2认同)