使用 Java 8 的给定日期(UTC 日期)和当前日期之间的天数差异
Difference between give date (UTC date) and current date in days using Java 8
我的方法的输入将是 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
正如您从这个帖子中看到的那样:
我更改了以下几行:
//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 小时,所以 returns 0
对于“2019-06-17T16:23:41.575 UTC”:
======================:2019-06-17T16:23:41.575 UTC
Until (with crono): 1
同样,由于超过 24 小时但不到 2 天,returns 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 ) ;
时区与时差的区别
你已经得到了两个很好的答案。您正在触及 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
是 ZoneId
).
一种适用于 Java 8 的格式器也是我们提供默认偏移量的格式器。为此,我们需要 DateTimeFormatterBuilder
:
final DateTimeFormatter formatter1 = new DateTimeFormatterBuilder()
.append(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
.appendLiteral(" UTC")
.parseDefaulting(ChronoField.OFFSET_SECONDS, 0)
.toFormatter();
另一个可能更简单的选择是首先解析为 LocalDateTime
(既不需要偏移量也不需要时区),然后通过调用 .atOffset(ZoneOffset.UTC)
转换为 OffsetDateTime
。
我的方法的输入将是 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
正如您从这个帖子中看到的那样:
我更改了以下几行:
//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 小时,所以 returns 0
对于“2019-06-17T16:23:41.575 UTC”:
======================:2019-06-17T16:23:41.575 UTC
Until (with crono): 1
同样,由于超过 24 小时但不到 2 天,returns 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 ) ;
时区与时差的区别
你已经得到了两个很好的答案。您正在触及 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
是 ZoneId
).
一种适用于 Java 8 的格式器也是我们提供默认偏移量的格式器。为此,我们需要 DateTimeFormatterBuilder
:
final DateTimeFormatter formatter1 = new DateTimeFormatterBuilder()
.append(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
.appendLiteral(" UTC")
.parseDefaulting(ChronoField.OFFSET_SECONDS, 0)
.toFormatter();
另一个可能更简单的选择是首先解析为 LocalDateTime
(既不需要偏移量也不需要时区),然后通过调用 .atOffset(ZoneOffset.UTC)
转换为 OffsetDateTime
。