使用Java 8的给出日期(UTC日期)和当前日期之间的差异(天)

时间:2019-06-18 22:24:22

标签: java datetime datetime-format datetimeoffset

我的方法的输入将是一个String,其中包含以UTC表示的日期。我需要将输入日期与当前日期和时间进行比较,并检查两个日期之间的差异。结果应该在几天之内。

我尝试以下操作均未成功。

String dateString = "2019-06-18T16:23:41.575 UTC";
final DateTimeFormatter formatter1 = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS 'UTC'").withZone(ZoneId.of("UTC"));
OffsetDateTime parsedDate  = OffsetDateTime.parse(dateString, formatter1);
System.out.println("======================:"+parsedDate.format(formatter1));


OffsetDateTime currentUTC = OffsetDateTime.now(ZoneOffset.UTC);
System.out.println("Until (with crono): " + parsedDate.until(currentUTC, ChronoUnit.DAYS));

我需要一个int(即天数)中的结果。

OffsetDateTime parsedDate = OffsetDateTime.parse(dateString, formatter1);行引发了以下堆栈跟踪的异常:

Exception in thread "main" java.time.format.DateTimeParseException: Text '2019-06-18T16:23:41.575 UTC' could not be parsed: Unable to obtain OffsetDateTime from TemporalAccessor: {InstantSeconds=1560875021},ISO,UTC resolved to 2019-06-18T16:23:41.575 of type java.time.format.Parsed
    at java.base/java.time.format.DateTimeFormatter.createError(DateTimeFormatter.java:1959)
    at java.base/java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1894)
    at java.base/java.time.OffsetDateTime.parse(OffsetDateTime.java:402)
    at thiagarajanramanathan.misc.App.main(App.java:86)
Caused by: java.time.DateTimeException: Unable to obtain OffsetDateTime from TemporalAccessor: {InstantSeconds=1560875021},ISO,UTC resolved to 2019-06-18T16:23:41.575 of type java.time.format.Parsed
    at java.base/java.time.OffsetDateTime.from(OffsetDateTime.java:370)
    at java.base/java.time.format.Parsed.query(Parsed.java:235)
    at java.base/java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1890)
    ... 3 more
Caused by: java.time.DateTimeException: Unable to obtain ZoneOffset from TemporalAccessor: {InstantSeconds=1560875021},ISO,UTC resolved to 2019-06-18T16:23:41.575 of type java.time.format.Parsed
    at java.base/java.time.ZoneOffset.from(ZoneOffset.java:348)
    at java.base/java.time.OffsetDateTime.from(OffsetDateTime.java:359)
    ... 5 more

3 个答案:

答案 0 :(得分:2)

从该线程可以看到:Unable to obtain OffsetDateTime from TemporalAccessor
                                                   我更改了以下几行:

//OffsetDateTime parsedDate  = OffsetDateTime.parse(dateString, formatter1);
ZonedDateTime parsedDate = ZonedDateTime.parse(dateString, formatter1);

使用此修改运行您的代码时,我可以获得以下结果

“ 2019-06-18T16:23:41.575 UTC”:

======================:2019-06-17T16:23:41.575 UTC
Until (with crono): 0

由于少于24小时,它返回0

“ 2019-06-17T16:23:41.575 UTC”:

======================:2019-06-17T16:23:41.575 UTC
Until (with crono): 1

类似地,由于时间超过24小时但不到2天,因此返回1。

我想这就是你想要的。请尝试一下,让我知道这是否适合您。

答案 1 :(得分:1)

解析

如果要使输入符合ISO 8601标准,我将简化解析。

String input = "2019-06-18T16:23:41.575 UTC".replace( " UTC", "Z" ) ;
Instant instant = Instant.parse( input ) ;

天数为24小时大块

如果您定义的经过时间是24小时,请使用Duration

Duration d = Duration.between( instant , Instant.now() ;
long days = d.toDays() ;

根据日历的天数

如果您希望从日历上看到经过的天数,这意味着日期而不是24小时的时间段,则必须指定一个时区。

ZoneId z = ZoneId.of( "Africa/Tunis" ) ;
ZonedDateTime zdt = instant.atZone( z ) ;
ZonedDateTime now = ZonedDateTime.now( z ) ;

提取日期。

LocalDate start = zdt.toLocalDate() ;
LocalDate stop = now.toLocalDate() ;
long days = ChronoUnit.DAYS.between( start , stop ) ;

答案 2 :(得分:1)

时区和偏移量之间的时差

您已经有两个不错的答案。您正在接触java.time的一个有趣且有点棘手的部分,因此我也想做出自己的贡献。我的要点是时区和UTC偏移量不相同。要获得OffsetDateTime,您需要一个偏移量。您通过格式化程序上的呼叫.withZone(ZoneId.of("UTC"))提供了一个时区,但这对您没有帮助。是的,您和我都知道UTC是所有偏移量的基础,因此它本身将偏移量定义为0。但是Java并未从您的代码中发现偏移量。

我承认我惊讶地发现以下简单更改足以使您的代码在Java 9上运行:

    final DateTimeFormatter formatter1
            = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS 'UTC'")
                    .withZone(ZoneOffset.UTC);

但是在Java 8上,我仍然遇到与以前相同的异常。我在Java 9.0.4上获得的输出是:

======================:2019-06-18T16:23:41.575 UTC
Until (with crono): 0

唯一的变化是我现在将ZoneOffset而不是ZoneId对象传递给withZone(这是可能的,因为ZoneOffset是{{1 }}。

在Java 8上也可以使用的格式化程序就是我们提供默认偏移量的格式化程序。为此,我们需要一个ZoneId

DateTimeFormatterBuilder

另一个可能更简单的选择是先解析为 final DateTimeFormatter formatter1 = new DateTimeFormatterBuilder() .append(DateTimeFormatter.ISO_LOCAL_DATE_TIME) .appendLiteral(" UTC") .parseDefaulting(ChronoField.OFFSET_SECONDS, 0) .toFormatter(); (既不需要偏移量也不需要时区),然后通过调用LocalDateTime转换为OffsetDateTime