考虑一下代码:
TemporalAccessor date = DateTimeFormatter.ofPattern("yyyy-MM-dd").parse("9999-12-31");
Instant.from(date);
最后一行抛出异常:
Unable to obtain Instant from TemporalAccessor: {},ISO resolved to 9999-12-31 of type java.time.format.Parsed
如何从Instant
模式创建yyyy-MM-dd
?
答案 0 :(得分:40)
字符串" 9999-12-31"仅包含有关日期的信息。它不包含有关时间或偏移的任何信息。因此,没有足够的信息来创建Instant
。 (其他日期和时间库更宽松,但java.time
避免默认这些值)
您的第一选择是使用LocalDate
而不是“Instant:
LocalDate date = LocalDate.parse("9999-12-31");
您的第二个选择是将处理日期转换为瞬间,这需要一个时区,此处选择为巴黎:
LocalDate date = LocalDate.parse("9999-12-31");
Instant instant = date.atStartOfDay(ZoneId.of("Europe/Paris")).toInstant();
您的第三个选择是将时区添加到格式化程序,并默认为时间:
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);
(如果这不起作用,请确保您拥有最新的JDK 8版本,因为此区域中已修复了错误。)
值得注意的是,这些可能性都不直接使用TemporalAccessor
,因为该类型是一个低级框架接口,而不是大多数应用程序开发人员使用的接口。
答案 1 :(得分:16)
问题不在于您使用的是9999年。Instant.MAX
字段的评估时间为1000000000-12-31T23:59:59.999999999Z
,因此一年的9999就可以了。
处理TemporalAccessors
而非LocalDateTime
或ZonedDateTime
等语义更丰富的类型就像使用Map
来建模对象及其属性而不是编写{ {1}} - 您必须确保该值具有接收它的内容所期望的字段(如秒,纳秒等),而不是依赖于更高级别类中的正式声明的操作以防止依赖性未被满足。
在你的情况下,时间访问器可能包含它给出的已解析日期字段,但没有"秒" class
需要的字段。在大多数情况下,最好使用更加语义丰富的类型,例如Instant
。
由于您只有日期字段,因此应将其解析为日期,然后在将时间字段转换为Instant之前添加时间字段。这是一种方法,使用LocalDate来解析日期:
LocalDateTime
答案 2 :(得分:4)
public static void main(String[] args) throws ParseException {
System.out.println(new SimpleDateFormat("yyyy-MM-dd").parse("2016-12-31").toInstant());
}
上面的代码给出了以下输出:
<强> 2016-12-31T00:00:00Z 强>
我已经使用java 8的功能(&#39; toInstant&#39;方法)回答了这个问题。希望这能回答你的问题......
答案 3 :(得分:0)
您只对日期本身感兴趣(9999年12月31日),在这种情况下,适当的类型将是LocalDate
:
LocalDate date = LocalDate.parse("9999-12-31");
或者您确实需要Instant
,在这种情况下,您需要设置时区和时区,例如东京的00:00
:
Instant instant = date.atStartOfDay(ZoneId.of("Asia/Tokyo")).toInstant();