首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用time4j将持续时间添加到某个时刻

使用time4j将持续时间添加到某个时刻
EN

Stack Overflow用户
提问于 2017-07-11 03:51:07
回答 1查看 246关注 0票数 3

当我使用java.time实现将代码转换为time4j时,我想向Moment添加一个Duration,但我得到了一个编译错误。在java.time下,我将执行以下操作:

代码语言:javascript
复制
val startTime: ZonedDateTime = ...
val duration: TemporalAmount = ...
val endTime: ZonedDateTime = startTime.plus(duration)

然而,使用time4j时,同样的方法不起作用:

代码语言:javascript
复制
val startTime: Moment = ...
val duration: Duration[ClockUnit] = ...
val endTime: Moment = startTime.plus(duration)

编译器抱怨DurationMoment之间的泛型交互。无论我以何种方式创建Duration (至少是我发现的),它都需要有一个与java.util.concurrent.TimeUnit相关联的泛型,因为Moment实现了TimePoint[java.util.concurrent.TimeUnit],因此Moment#plus方法需要一个与Moment相同的Duration[java.util.concurrent.TimeUnit]作为时间单元。

这让我感到惊讶的是,java.util.concurrent.TimeUnit被使用了,因为它不是time4j类型。我是不是错过了这个选择的更详细的细节?我的印象是,这是由设计决定的。

工作的一种方法是如果我使用一个PlainTimestamp并添加一个Duration[ClockUnit | CalendarUnit | IsoUnit],因为前者实现了TimePoint[IsoUnit, PlainTime]并重载了额外支持的单元。然后,我可以将PlainTimestamp转换为以后需要的任何时区。这是预定的设计吗?

(仍然是:)与Moment.plus方法一起使用的合适的Moment.plus类型是什么?

我使用的是time4j版本4.27.2

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-07-12 08:32:30

简短答案如何迁移zonedDateTime.plus(Duration.ofHours(24))

代码语言:javascript
复制
Moment.from(zonedDateTime.toInstant()).plus(MachineTime.of(24, TimeUnit.HOURS));

还请参见全局持续时间类型MachineTime的API。

详细回答

java.time-API只知道一个类ChronoUnit来表示适用于任意时态实体的最常用的时态单元(以及通用接口TemporalUnit),与之不同的是,库Time4J的单元和持续时间设计要细得多。

  • 具有时间线的每个日历或时态类型都有自己的单元类型,这也以不同的方式描述时间类型的时间线,因此即使编译器也会告诉您不要混淆不同实体的不同单元类型,如Moment (对应于java.time.Instant)或PlainTimestamp (对应于LocalDateTime)。
  • 这种区别被设计为超类TimePoint中的泛型类型参数U。对于具体的类:Moment主要使用java.util.concurrent.TimeUnit,而PlainTimestamp则处理IsoUnit的任何实现,特别是枚举CalendarUnitClockUnit
  • 广义持续时间概念由接口TimeSpan描述,该接口也由所使用的单元类型U指定。只有当单元类型为java.util.concurrent.TimeUnit时,才能将timespan添加到某个时刻。这是由特殊的实现类MachineTime提供的。此外,另一个称为net.time4j.Duration的持续时间实现只与本地类型(如PlainTimestamp )兼容。
  • 特殊的时间实体有自己的一套合适的单位。例如,电子逆向拍卖的单位只存在于日本日历中,而不存在于具有零、一或两个电子逆向日历的其他日历中。

为什么Moment PlainTimestamp**?**和的单元类型不同?

这部分已经得到了最后一项关于合适的单元集的回答。例如,像Moment这样的类似机器的类型,几个月和几年都没有多大意义。因此,所选的枚举java.util.concurrent.TimeUnit涵盖了Moment所需的单元。

此外,不同的单元类型的Time4J有助于区分。net.time4j.Duration<ClockUnit>在本地上下文中计算,而MachineTime<TimeUnit>计算为全局持续时间。这不仅适用于时钟相关的单位,如小时,也适用于日历单位。一年不只是一年。我们有ISO-日历年(相当于公历年).我们有ISO周为基础的年份(时间为364天或371天).我们有伊斯兰时代(354天或355天)等等。因此,Time4J知道很多不同的日历单元(注意日历模块的API )。所以Time4J最终采用了一种设计来防止对不同单位类型的持续时间的比较(这就像比较苹果和橙子一样)。

以下是萨摩亚很少改变国际日期的例子(2011-12-30被排除在外),说明单位类型的区别可能是多么重要:

在Time4J中,我们只使用不同的单元类型来表示算法是发生在局部还是在全局时间线上。结论:在Java-8中,我们必须仔细研究上下文,在Time4J中,单元类型提供了有价值的额外信息。

代码语言:javascript
复制
ZonedDateTime zdt = ZonedDateTime.of(2011, 12, 29, 0, 0, 0, 0, "Pacific/Apia");
Moment m1 = Moment.from(zdt.toInstant());
Moment m2 = m1.plus(MachineTime.of(24, TimeUnit.HOURS));
assertThat(m2.isSimultaneous(m1.plus(MachineTime.of(1, TimeUnit.DAYS))), is(true));
System.out.println(m2); // 2011-12-30T10:00:00Z
System.out.println(m2.toZonalTimestamp(PACIFIC.APIA)); // 2011-12-31T00
System.out.println(m1.toZonalTimestamp(PACIFIC.APIA).plus(2, CalendarUnit.DAYS)); // 2011-12-31T00

TimeUnit.DAYSCalendarUnit.DAYS显然是不一样的。它们甚至需要不同的数量(1比2)才能产生相同的结果。

旁注:

我现在缩短了我答案的第一个版本--主要是省略了与Java-8相关的内容,因为我认为,在你问题的狭隘背景下,很容易写太多关于单元/持续时间的设计(我甚至没有给出任何完整的答案)。像这里这样的教程页面或额外的文档页面确实是一个更好的地方。

但至少还有两点在我的回答中没有提到,您可能也很感兴趣(关注点是net.time4j.Duration):标志处理和专用时区-公制。在某些情况下,最后一个甚至可以作为MachineTime的替代方案。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/45025055

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档