将Instant转换为OffsetDateTime,然后将OffsetDateTime上的Instant.parse()



我正在接收来自服务的即时消息,下面是一些情况。

在第一种情况下,比如instant = "2021-03-23T04:17:35Z"&在第二种情况下,instant = "2021-07-15T05:27:00Z"

然后需要将即时转换为offsetDateTime,就像一样

OffsetDateTime offsetDateTime = instant.atOffset(ZoneOffset.UTC)

现在我想计算上面的offsetDateTime和instant.Now 之间的小时间隔

ChronoUnit.HOURS.between(Instant.parse(offsetDateTime), Instant.now())

结果

情况1:它工作良好

情况2:错误:DateTimeParseException: Text '2021-07-15T05:27Z' could not be parsed at index 16

找出原因:在情况2中,如果它通过相同的2021-07-15T05:27:00Z。它会起作用,但由于instant.atOffset(ZoneOffset.UTC)内部会调用下面的方法,其中零将被移除,基本上会对微小部分进行排序。所以下面的fn将返回2021-07-15T05:27Z,这将导致DateTimeParseException。

public static OffsetDateTime ofInstant(Instant instant, ZoneId zone) {
Objects.requireNonNull(instant, "instant");
Objects.requireNonNull(zone, "zone");
ZoneRules rules = zone.getRules();
ZoneOffset offset = rules.getOffset(instant);
LocalDateTime ldt = LocalDateTime.ofEpochSecond(instant.getEpochSecond(), instant.getNano(), offset);
return new OffsetDateTime(ldt, offset);
}

我假设的一个解决方案是手动附加零,但这可能不是一个好的做法。

您不需要DateTimeFormatter

您不需要任何DateTimeFormatter来解析日期时间字符串。现代的Date-Time API基于ISO8601,只要Date-Time字符串符合ISO8601标准,就不需要显式使用DateTimeFormatter对象。

import java.time.Instant;
import java.time.temporal.ChronoUnit;
public class Main {
public static void main(String[] args) {
Instant instant1 = Instant.parse("2021-03-23T04:17:35Z");
Instant instant2 = Instant.parse("2021-07-15T05:27:00Z");
System.out.println(instant1);
System.out.println(instant2);
System.out.println(ChronoUnit.HOURS.between(instant1, instant2));
}
}

输出:

2021-03-23T04:17:35Z
2021-07-15T05:27:00Z
2737

在线演示

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

Avinash的回答是正确的。

此外,让我们看看问题:中的代码

public static OffsetDateTime ofInstant(Instant instant, ZoneId zone) 
{
Objects.requireNonNull(instant, "instant");
Objects.requireNonNull(zone, "zone");

ZoneRules rules = zone.getRules();
ZoneOffset offset = rules.getOffset(instant);
LocalDateTime ldt = LocalDateTime.ofEpochSecond(instant.getEpochSecond(), instant.getNano(), offset);
return new OffsetDateTime(ldt, offset);
}

首先,如果要将偏移应用于力矩,则不需要LocalDateTime类。只需这样做:

OffsetDateTime odt = instant.atOffset( myZoneOffset ) ;

请参阅有关at…from…with…等的命名约定的教程。

当你想感知一个时刻,比如特定地区的人使用的挂钟时间时,将时区(ZoneId(应用于Instant,得到ZonedDateTime。使用ZonedDateTime而不是OffsetDateTime。CCD_ 19比单纯的CCD_ 20更可取,因为它包含更多的信息。如果加或减到另一个时刻,这个信息可能是至关重要的。当生成表示此日期-时间对象内容的文本时,此信息也很有用。

要明白,与UTC的偏移量只是小时-分-秒的数量。时区远不止这些。时区是由政治家决定的特定地区人民使用的偏移量的过去、现在和未来变化的历史。

ZonedDateTime zdt = instant.atZone( myZoneId ) ;

所以你的方法应该是这样的。

public static ZonedDateTime ofInstant(Instant instant, ZoneId zone) 
{
ZonedDateTime zdt = 
Objects.requireNonNull( instant )
.atZone(
Objects.requireNonNull( zone )
)
;
return zdt ;
}

如果您确实需要OffsetDateTime,尽管ZonedDateTime是首选,请提取一个。

OffsetDateTime odt = zdt.toOffsetDateTime() ;

最新更新