Java 8:计算两个 ZonedDateTime 之间的差异

新手上路,请多包涵

我正在尝试编写一种方法来打印两个 ZonedDateTime 之间的时差,关于时区之间的差异。

我找到了一些解决方案,但所有这些解决方案都是为与 LocalDateTime 一起使用而编写的。

原文由 Maggie Hill 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1k
2 个回答

您可以使用 ChronoUnit 之间 的方法。

此方法将这些时间转换为相同的区域(来自第一个参数的区域),然后调用在 Temporal 接口中声明的 until 方法:

 static long zonedDateTimeDifference(ZonedDateTime d1, ZonedDateTime d2, ChronoUnit unit){
    return unit.between(d1, d2);
}

由于 ZonedDateTimeLocalDateTime 都实现了 Temporal 接口,您还可以为这些日期时间类型编写通用方法:

 static long dateTimeDifference(Temporal d1, Temporal d2, ChronoUnit unit){
    return unit.between(d1, d2);
}

但请记住,为混合的 LocalDateTimeZonedDateTime 调用此方法会导致 DateTimeException

希望能帮助到你。

原文由 Michał Szewczyk 发布,翻译遵循 CC BY-SA 3.0 许可协议

tl;博士

小时、分钟、秒:

 Duration.between( zdtA , zdtB )  // Represent a span-of-time in terms of days (24-hour chunks of time, not calendar days), hours, minutes, seconds. Internally, a count of whole seconds plus a fractional second (nanoseconds).

年、月、日:

 Period.between(                  // Represent a span-of-time in terms of years-months-days.
    zdtA.toLocalDate() ,         // Extract the date-only from the date-time-zone object.
    zdtB.toLocalDate()
)

细节

Michal S 的回答 是正确的,显示 ChronoUnit

Duration & Period

另一条路线是 DurationPeriod 类。第一个用于较短的时间跨度(小时、分钟、秒),第二个用于较长的时间跨度(年、月、天)。

 Duration d = Duration.between( zdtA , zdtB );

通过调用 toString 生成 标准 ISO 8601 格式 的字符串。格式为 PnYnMnDTnHnMnS 其中 P 标记开始, T 分隔两部分。

 String output = d.toString();

在 Java 9 及更高版本中,调用 to…Part 方法来获取各个组件。在 我的另一个答案中 讨论过。

示例代码

ZoneId z = ZoneId.of( "America/Montreal" );
ZonedDateTime zdtStart = ZonedDateTime.now( z );
ZonedDateTime zdtStop = zdtStart.plusHours( 3 ).plusMinutes( 7 );

Duration d = Duration.between( zdtStart , zdtStop );

2016-12-11T03:07:50.639-05:00[美国/蒙特利尔]/2016-12-11T06:14:50.639-05:00[美国/蒙特利尔]

PT3H7M

请参阅 IdeOne.com 中的实时代码

Interval & LocalDateRange

ThreeTen-Extra 项目向 java.time 类添加了功能。其中一个方便的类是 Interval 将时间跨度表示为时间轴上的一对点。另一个是 LocalDateRange ,用于一对 LocalDate 对象。相比之下, Period & Duration 类每个都代表一个时间跨度,因为 没有 附加到时间线。

Interval 的工厂方法采用一对 Instant 对象。

 Interval interval = Interval.of( zdtStart.toInstant() , zdtStop.toInstant() );

您可以从 Duration 获得 Interval

 Duration d = interval.toDuration();


Java 和 ThreeTen-Extra 项目中的时间跨度类表


关于 java.time

java.time 框架内置于 Java 8 及更高版本中。这些类取代了麻烦的旧 日期时间类,例如 java.util.DateCalendarSimpleDateFormat

现在处于 维护模式Joda-Time 项目建议迁移到 java.time 类。

要了解更多信息,请参阅 Oracle 教程。并在 Stack Overflow 中搜索许多示例和解释。规范是 JSR 310

您可以直接与数据库交换 java.time 对象。使用符合 JDBC 4.2 或更高版本的 JDBC 驱动程序。不需要字符串,不需要 java.sql.* 类。

在哪里获取 java.time 类?

ThreeTen-Extra 项目用附加类扩展了 java.time。该项目是未来可能添加到 java.time 的试验场。您可能会在这里找到一些有用的类,例如 IntervalYearWeekYearQuarter 等等

原文由 Basil Bourque 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题