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


79

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

我找到了一些解决方案,但所有解决方案均编写为可与LocalDateTime一起使用


2
发表您要实现的目标的具体示例,并从中获得结果。
JB Nizet

2
Michał的答案正是我所期望的。非常感谢!
玛姬·希尔

Answers:


95

您可以使用方法之间ChronoUnit

此方法将那些时间转换为相同的区域(第一个参数的区域),然后,调用直到Temporal接口中声明的方法为止

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

希望能帮助到你。


有没有办法得到两个ZDT类型之间的ZoneId不同的两个ZDT类型之间的差异?
stanlick

@stanlick是:Duration.between( zdtA , zdtB )我的答案所示。我想between方法只是ZonedDateTime::toInstant()在两者上调用。
罗勒·布尔克

71

tl; dr

对于小时,分钟,秒:

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

DurationPeriod

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

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

通过调用产生标准ISO 8601格式的字符串toString。格式是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中的实时代码

IntervalLocalDateRange

ThreeTen-EXTRA项目将功能添加到java.time类。它的便捷类之一是Interval将时间跨度表示为时间轴上的一对点。另一个是LocalDateRange,用于一对LocalDate对象。相反,PeriodDuration类分别表示附加到时间轴上的时间跨度。

用于的工厂方法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.DateCalendar,和SimpleDateFormat

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

要了解更多信息,请参见Oracle教程。并在Stack Overflow中搜索许多示例和说明。规格为JSR 310

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

在哪里获取java.time类?

ThreeTen-额外项目与其他类扩展java.time。该项目为将来可能在java.time中添加内容打下了基础。你可能在这里找到一些有用的类,比如IntervalYearWeekYearQuarter,和更多


您在哪里看到of持续时间需要两个瞬间的方法?我只看到public static Duration of(long amount, TemporalUnit unit)
Brian Gordon

@BrianGordon固定,替换.of.between。谢谢。
罗勒·布尔克

持续时间与ZonedDateTime一起使用,而Period与LocalDate一起使用。需要在我们的zdt对象上调用toLocalDate()方法。
guillaume guerin,

1
@guillaumeguerin你是正确的。修复了我的代码示例。谢谢。
罗勒·布尔克

哦,非常感谢,您的榜样非常好!
布伦登·岩田
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.