首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Java 8分析ISO-8601日期忽略时区的存在(或缺席)

Java 8分析ISO-8601日期忽略时区的存在(或缺席)
EN

Stack Overflow用户
提问于 2017-09-25 17:10:02
回答 2查看 2.6K关注 0票数 7

我的应用程序应该能够解析日期,忽略时区(我总是知道它是UTC)。问题是日期可能有以下两种形式-

2017-09-11T12:44:07.793Z

0001-01-01T00:00:00

我可以使用LocalDateTime解析第一个,使用Instant类解析第二个。有没有办法用一个单一的机制来做到这一点?

我试图避免在输入字符串的末尾硬编码Z

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-09-25 17:27:31

如果Z偏移量是可选的,则可以使用带有可选部分的java.time.format.DateTimeFormatterBuilder

代码语言:javascript
复制
DateTimeFormatter fmt = new DateTimeFormatterBuilder()
    // date/time
    .append(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
    // optional offset
    .optionalStart().appendOffsetId()
    // create formatter
    .toFormatter();

然后可以使用parseBest方法,其中包含试图创建对应对象的TemporalQuery列表。然后检查返回类型并相应地执行以下操作:

代码语言:javascript
复制
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:00ZInstant

在上面的示例中,我只使用了Instant::fromLocalDateTime::from,因此格式化程序首先尝试创建一个Instant。如果不可能,则尝试创建一个LocalDateTime。您可以向该列表中添加任意数量的类型(例如,我可以添加ZonedDateTime::from,如果创建了ZonedDateTime,则可以使用toInstant()方法将其转换为Instant )。

如您所知,输入始终在UTC中,您也可以在格式化程序中直接设置它:

代码语言:javascript
复制
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

代码语言:javascript
复制
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
票数 13
EN

Stack Overflow用户

发布于 2017-09-25 17:16:36

你可以"parseBest",就像这样:

代码语言:javascript
复制
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检查来进行结果解析(尽管不是没有一个强制转换):

代码语言:javascript
复制
Instant parsed = (Instant) parser.parseBest(inputString,
                    Instant::from,
                    interResult -> LocalDateTime.from(interResult).atZone(ZoneOffset.UTC).toInstant())

注意,第二个选项使用lambda,它将LocalDateTime转换为ZonedDateTime,然后转换为Instant,因此解析结果总是强制到Instant

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46410624

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档