【问题标题】:Java 1.8 time functionalityJava 1.8 时间功能
【发布时间】:2014-06-28 21:26:45
【问题描述】:

所以 Java 1.8 带有一组全新(和旧)类来管理时间计算:java.time.Instantjava.time.LocalTimejava.time.temporal.ChronoUnit,也许还有更多......

但是为什么没有简单的方法来计算其中任何一个之间的时间差?我希望“time_later - time_earlier”是最常用的时间操纵,但这无处可寻。我不能从另一个中减去一个 LocalTime 并获得一个新的 LocalTime;我不能从另一个 Instant 中减去一个 Instant 以获得新的 Instant。相反,我必须摆弄 ChronoUnits.between、长毫秒和诸如此类的东西来实现这个非常有用的东西。

这是为什么?一定有一些我没有得到的事情发生吗?还是我很傻……?

【问题讨论】:

  • 因为 Java 只为原语定义运算符。要点是获得两次之间的差异并不简单。闰年/秒呢?不同的时区?夏令时?本地时间不连续?
  • 所以.. 因为它不简单所以不可用。是这样吗?我的想法正好相反……因为它并不简单,所以应该一劳永逸地正确实现。
  • 不,它不可用,因为不清楚time1 - time2 应该做什么!见上文。
  • 计算两个日期/时间之间的差异实际上是非常复杂的,当你包括闰年、千年和世纪边界之类的东西时,这就是我们有 Duration 类的原因。更多详情请查看Date and Time
  • 飞行时的持续时间通常基于从飞行者的角度可观察到的时间量。这并不意味着 10 小时的飞行会让你向后或向前 10 小时

标签: java time java-8 java-time


【解决方案1】:

在 Java 8 之前,您的问题的通常答案是“使用 Joda Time”

但 Joda Time 的作者 (Stephen Colebourne) 深入参与了新的 Java 8 时间类和方法。这里有两篇非常好的文章:

对于您的具体问题,您可能需要考虑 Java 8“Duration”和“LocalTime”、“LocalDate”和/或“LocalTimeDate”(以及其他选项):

// A duration of 3 seconds and 5 nanoseconds
Duration duration = Duration.ofSeconds(3, 5);
Duration oneDay = Duration.between(today, yesterday);

// Tomorrow
LocalDate tomorrow = LocalDate.now().plusDays(1);

// Yesterday
LocalDate yesterday = LocalDate.now().plusDays(-1);

// before 5 houres and 30 minutes
LocalDateTime dateTime = LocalDateTime.now().minusHours(5).minusMinutes(30);

【讨论】:

  • 我认为 OP 知道 Period 或 Duration 等类,但他想要一些不可能的东西 - 请参阅我的答案。
  • 仅供参考,Joda-Time 比 java.time 有一些优势。 Joda-Time 和 java.time 各有利弊。幸运的是,如果我们小心 import 语句,我们可以同时使用两者。另外,还有一个project adding more features to java.time
【解决方案2】:

引用:

“我不能从另一个中减去一个 LocalTime 并得到一个新的 LocalTime”

这是一个根本错误的想法的主要原因是物理和数学问题。 LocalTimeInstant 等对象代表时间轴上的一个时间点。但是两个时间点之间的差异只能是一个持续时间,也就是一个时间长度。从数学上讲,您会在另一个维度(点与线)中得到结果。 所以两个时间点相减不能得出另一个时间点。

但是用单位来测量两个时间点之间的距离是有意义的,正如您正确看到的那样,JSR-310(又名 java.time-package)支持此操作。顺便说一句,持续时间/周期的计算在某种程度上是有限的(即没有像 Joda-Time 那样的混合年、天、小时之间的操作),但一般来说,像 ChronoUnit 类中的中间方法并不复杂“摆弄”。它简单易懂。

【讨论】:

  • 是的,我今天早上意识到这是显而易见的答案。 Instant、LocalTime等代表时间点,减去它们会产生一个时间间隔,当然不能用时间点来表示。我的错...谢谢
  • @OppfinnarJocke 好吧,我怀疑有些人已经使用Date 作为持续时间类型的替代品,因为 JDK 没有提供这样的类型。当然,这一直是一种危险的变通方法,或者相当肮脏的 hack,因为有时人们也忘记将时区设置为 UTC,然后甚至没有意识到奇怪的时区副作用......
【解决方案3】:

提供了计算两个时间点之间差异的方法。

Instant a = Instant.now().minusSeconds(2);
Instant b = Instant.now().plusSeconds(2);

Duration difference = Duration.between(a, b);

long secsBetween1 = a.until(b, ChronoUnit.SECONDS);
long secsBetween2 = ChronoUnit.SECONDS.between(a, b);

Duration是表示时间量的主要对象,Duration.between是创建它的关键方法。

ChronoUnit.betweenTemporal.until 是稍低级别的方法,它们将差异返回为特定单元的 long

【讨论】:

    【解决方案4】:

    您可以使用java.time.Instant.toEpochMilli() 获得您想要的功能。这为您提供与旧 java.util.Date.getTime() 相同的功能。

    只要您不必处理时区,Instant 几乎就是您所需要的。不要被其他的东西弄糊涂了。

    如果您确实必须处理时区,则需要大量复杂性,尽管由于过于笼统,包中存在一些额外的复杂性。

    【讨论】:

    • 如果您不必处理时区,LocalXxx 比 Instant 更合适,它让您回到传统日期 API 的地狱......
    • @assylias 实际上,如果您不必处理时区,旧版 Date API 可以正常工作。只有当您需要开始在不同的时区表达事物时,它才会成为问题。相反,如果你不小心,使用 LocalXxx 类会给你带来各种各样的麻烦。例如,它们不能用作时间戳,因为它们不标识单个时间点,而是标识不同时区的不同时间点。
    猜你喜欢
    • 1970-01-01
    • 2011-02-20
    • 2018-03-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-19
    • 2015-08-18
    • 2021-03-07
    相关资源
    最近更新 更多