我的应用程序应该能够解析日期,忽略时区(我总是知道它是UTC)。问题是日期可能有以下两种形式-
2017-09-11T12:44:07.793Z
0001-01-01T00:00:00
我可以使用LocalDateTime解析第一个,使用Instant类解析第二个。有没有办法用一个单一的机制来做到这一点?
我试图避免在输入字符串的末尾硬编码Z
发布于 2017-09-25 17:27:31
如果Z偏移量是可选的,则可以使用带有可选部分的java.time.format.DateTimeFormatterBuilder:
DateTimeFormatter fmt = new DateTimeFormatterBuilder()
// date/time
.append(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
// optional offset
.optionalStart().appendOffsetId()
// create formatter
.toFormatter();然后可以使用parseBest方法,其中包含试图创建对应对象的TemporalQuery列表。然后检查返回类型并相应地执行以下操作:
Instant instant = null;
// tries to create Instant, and if it fails, try a LocalDateTime
TemporalAccessor parsed = fmt.parseBest("2017-09-11T12:44:07.793Z", Instant::from, LocalDateTime::from);
if (parsed instanceof Instant) {
instant = (Instant) parsed;
} else if (parsed instanceof LocalDateTime) {
// convert LocalDateTime to UTC instant
instant = ((LocalDateTime) parsed).atOffset(ZoneOffset.UTC).toInstant();
}
System.out.println(instant); // 2017-09-11T12:44:07.793Z使用第二个输入(0001-01-01T00:00:00)运行将产生相当于0001-01-01T00:00:00Z的Instant。
在上面的示例中,我只使用了Instant::from和LocalDateTime::from,因此格式化程序首先尝试创建一个Instant。如果不可能,则尝试创建一个LocalDateTime。您可以向该列表中添加任意数量的类型(例如,我可以添加ZonedDateTime::from,如果创建了ZonedDateTime,则可以使用toInstant()方法将其转换为Instant )。
如您所知,输入始终在UTC中,您也可以在格式化程序中直接设置它:
DateTimeFormatter fmt = new DateTimeFormatterBuilder()
// date/time
.append(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
// optional offset
.optionalStart().appendOffsetId()
// create formatter with UTC
.toFormatter().withZone(ZoneOffset.UTC);所以您可以直接将其解析为Instant。
System.out.println(Instant.from(fmt.parse("2017-09-11T12:44:07.793Z"))); // 2017-09-11T12:44:07.793Z
System.out.println(Instant.from(fmt.parse("0001-01-01T00:00:00"))); // 0001-01-01T00:00:00Z发布于 2017-09-25 17:16:36
你可以"parseBest",就像这样:
DateTimeFormatter parser = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss[Z]");
Temporal parsed = parser.parseBest(inputString, Instant::from, LocalDateTime::from);然后,你应该检查什么被解析,并采取相应的行动。parseBest方法将使用任何类型的TemporalQuery,包括java.time类上可用的大多数from方法。例如,你可以用LocalDate.from来延长这个列表。
您还可以使用该方法和lambdas强制将解析结果强制转换为您想要的类型,而不需要外部的instanceof检查来进行结果解析(尽管不是没有一个强制转换):
Instant parsed = (Instant) parser.parseBest(inputString,
Instant::from,
interResult -> LocalDateTime.from(interResult).atZone(ZoneOffset.UTC).toInstant())注意,第二个选项使用lambda,它将LocalDateTime转换为ZonedDateTime,然后转换为Instant,因此解析结果总是强制到Instant。
https://stackoverflow.com/questions/46410624
复制相似问题