添加一个 Java 8 ISO 8601 持续时间表达式到 java.util.Date

Add a Java 8 ISO 8601 time duration expression to java.util.Date

我有一个表达式,如 "PT20.345S""P2DT3H4M" 等,如此处所述 https://docs.oracle.com/javase/8/docs/api/java/time/Duration.html#parse-java.lang.CharSequence-

我如何解析它,将它添加到当前时间并得到一个 java.util.Date 对象?

均无效:

Date d1 = Date.from(LocalDateTime.now().plus(Duration.parse(_expression)));
Date d2 = Date.from(Duration.parse(_expression).addTo(LocalDateTime.now()));

在您的代码中,如果您使用 ZoneOffsetLocalDateTime 转换为 Instant(例如 UTC,或使用 ZoneOffset.systemDefault() 的系统默认值,则第一个解决方案应该有效) 如下所示:

Date d1 = Date.from(LocalDateTime.now().plus(Duration.parse(_expression)).toInstant(OffsetDateTime.now().getOffset());

但是,LocalDateTime在这种情况下是错误使用的,因为它不代表一个时刻,不是时间轴上的一个点

来自javadoc

This class does not store or represent a time-zone. Instead, it is a description of the date, as used for birthdays, combined with the local time as seen on a wall clock. It cannot represent an instant on the time-line without additional information such as an offset or time-zone.

但是,Instant 是 UTC 时间轴上的一个时刻

This class models a single instantaneous point on the time-line. This might be used to record event time-stamps in the application.

因此,如果您使用 Instant,则无论时区如何,您都可以准确知道所指的时间点。由于您要处理业务逻辑,例如将时间量添加到当前时间并转换为日期,因此使用起来很方便 class。

 Date date1 = Date.from(Instant.now().plus(Duration.parse("PT20.345S")));
Duration amountToAdd = Duration.parse("PT20.345S");  // Represent a span of time. Here, about twenty and a third seconds.
Instant now = Instant.now() ;                        // Capture the current moment in UTC.
Instant otherMoment = now.plus(amountToAdd);         // Add the span-of-time to the current moment, for a moment in the future (or in the past if the duration is negative).
String output = otherMoment.toString():              // Generate a String in standard ISO 8601 format.

2018-06-30T19:34:47Z

从现代 java.time class 转换为传统 class.

Date date1 = Date.from(otherMoment);
System.out.println(date1);

运行刚才在Europe/Copenhagen时区我得到:

Sat Jun 30 21:34:47 CEST 2018

如果我使用您的其他示例持续时间字符串 P2DT3H4M,我得到:

Tue Jul 03 00:38:26 CEST 2018

或者如果你喜欢单线:

    Date date1 = Date.from(Instant.now().plus(Duration.parse("PT20.345S")));

java.util.Date class 早就过时了,所以理想情况下你不应该想要一个。如果您无论如何都需要一个,通常是您现在无法更改或不想更改的遗留 API,那么在使用 java.time 执行尽可能多的逻辑时,您的想法是正确的,现代 Java 日期和时间 API,最后只转换为 DateDate 在现代世界的近亲是 InstantInstantDate 之间存在直接转换,这就是我使用这个 class 的原因。 Instant 独立于区域偏移量和时区也很可爱。