使用time4j添加持续时间

时间:2017-07-11 03:51:07

标签: scala time4j

当我使用 java.time 实现将代码转换为 time4j 时,我想向<item name="colorAccent">#BA55D3</item> 添加Duration但是我得到编译错误。在 java.time 下,我会执行以下操作:

Moment

虽然使用 time4j ,但同样不起作用:

val startTime: ZonedDateTime = ...
val duration: TemporalAmount = ...
val endTime: ZonedDateTime = startTime.plus(duration)

编译器抱怨val startTime: Moment = ... val duration: Duration[ClockUnit] = ... val endTime: Moment = startTime.plus(duration) Duration之间的泛型交互。无论我以哪种方式创建Moment(至少我发现的),都需要有Duration的关联通用,因为java.util.concurrent.TimeUnit实现了Moment和{因此,{1}}方法需要TimePoint[java.util.concurrent.TimeUnit]与时间单位相同的关联泛型Moment#plus

令我惊讶的是Duration[java.util.concurrent.TimeUnit]被使用,因为这不是 time4j 类型。我错过了这个选择的细节吗?我的印象是这是由设计决定的。

一种方法是使用Moment并添加java.util.concurrent.TimeUnit,因为前一种类型实现PlainTimestamp并重载额外支持的单位。然后我可以将Duration[ClockUnit | CalendarUnit | IsoUnit]转换为我之后需要的任何时区。这是预期的设计吗?

(仍然是:) TimePoint[IsoUnit, PlainTime]方法使用的PlainTimestamp类型是什么?

我正在使用time4j版本4.27.2

1 个答案:

答案 0 :(得分:1)

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

Moment.from(zonedDateTime.toInstant()).plus(MachineTime.of(24, TimeUnit.HOURS));

另请参阅全球持续时间类型MachineTime的API。

详尽的答案

java.time - API相比,它只知道一个单一类ChronoUnit,用于表示适用于任意时间实体(以及通用接口TemporalUnit)的最常用时间单位,图书馆Time4J的单位和持续时间设计更精细。

  • 每个具有时间轴的日历或时间类型都有自己的单元类型,它也以不同的方式表征时间类型的时间线,因此即使编译器也会告诉您不要混淆不同实体的不同单元类型,如{{1 }(与Moment对应)或java.time.Instant(与PlainTimestamp对应)。
  • 这种区别在设计中被编码为超类TimePoint中的泛型类型参数U.对于具体类:LocalDateTime主要与Moment一起使用,而java.util.concurrent.TimeUnit适用于PlainTimestamp的任何实现,尤其是枚举IsoUnitCalendarUnit
  • 通用持续时间概念由接口TimeSpan描述,接口Sign handling也由要使用的单元类型U指定。如果单位类型为ClockUnit,则只能添加一个时间跨度。这是由特殊实现类java.util.concurrent.TimeUnit提供的。此外,名为MachineTime的其他持续时间实施仅与net.time4j.Duration等本地类型兼容。
  • 特殊时间实体有自己的一组合适的单位。例如,时代单位仅存在于日历中,但不存在于零,一或两个时代的其他日历中。

为什么PlainTimestampMoment的单位类型不同?

部分关于合适的单位组的最后一项已经回答了这个问题。例如,月份和年份对于类似机器的类型PlainTimestamp没有多大意义。因此,所选的枚举Moment涵盖了java.util.concurrent.TimeUnit所需的单位。

此外,Time4J的不同单位类型有助于区分。 Moment在本地环境中计算,而net.time4j.Duration<ClockUnit>计算为全局持续时间。这不仅适用于时钟相关单位,如小时数,也适用于日历单位。一年不仅仅是一年。我们有ISO日历年(对应格里高利年)。我们有基于ISO周的年份(长度为364或371天)。我们有伊斯兰年(354或355天)等等。因此,Time4J知道许多不同的日历单元(注意日历模块的API)。 因此Time4J最终采用了一种设计来防止持续时间与不同单位类型的比较(这就像比较苹果和橙子一样)。

以下是关于改变萨摩亚国际日期线的罕见情况的例子(2011-12-30被遗漏)表明单位类型的区别可能是多么重要:

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

MachineTime<TimeUnit>

对象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.DAYS显然不一样。它们甚至需要不同的量(1对2)才能产生相同的结果。

旁注:

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

但至少在我的回答中没有提到的其他两点也可能对你有用(关注CalendarUnit.DAYS):timezone-metric和专门的Jsfiddle。在某些情况下,最后一个甚至可以替代net.time4j.Duration