288

我知道有关于java.util.Date和 Joda-Time 的问题。但是经过一番挖掘,我找不到关于java.time APIJava 8中的新功能,由JSR 310定义)和Joda-Time之间差异的线程。

我听说 Java 8 的 java.time API 比 Joda-Time 更干净,可以做更多的事情。但我找不到比较两者的例子。

  • java.time 能做什么而 Joda-Time 不能?
  • java.time 能比 Joda-Time 做得更好吗?
  • java.time 的性能更好吗?
4

4 回答 4

452

共同特征

a) 两个库都使用不可变类型。Joda-Time 还提供了额外的可变类型,例如MutableDateTime.

b) 此外:这两个库都受到Eric Evans 的设计研究“TimeAndMoney”或Martin Fowler 关于域驱动风格的想法的启发,因此它们或多或少地为流畅的编程风格而努力(尽管并不总是完美的;-))。

c) 通过这两个库,我们得到了一个真正的日历日期类型(称为LocalDate)、一个真正的挂钟类型(称为LocalTime)和组合(称为LocalDateTime)。java.util.Calendar与旧和相比,这是一个非常大的胜利java.util.Date

d) 两个库都使用以方法为中心的方法,这意味着它们鼓励用户使用getDayOfYear()而不是get(DAY_OF_YEAR). 与 相比,这会导致很多额外的方法java.util.Calendar(尽管后者由于过度使用 int 而根本不是类型安全的)。

表现

尽管第 3 点(异常捕获)可能已过时,但请参阅@OO7 的另一个答案,指向 Mikhail Vorontsov 的分析 - 请参阅此 JDK-bug。不同的性能(这通常有利于JSR-310)主要是由于Joda-Time的内部实现总是使用类似机器时间的长原语(以毫秒为单位)。

空值

Joda-Time 通常使用 NULL 作为系统时区、默认语言环境、当前时间戳等的默认值,而 JSR-310 几乎总是拒绝 NULL 值。

精确

JSR-310 处理纳秒精度,而 Joda-Time 仅限于毫秒精度。

支持的字段:

java-8 (JSR-310) 中支持的字段的概述由 temporal-package 中的一些类(例如ChronoFieldWeekFields)给出,而 Joda-Time 在这方面相当薄弱 - 请参阅DateTimeFieldType。Joda-Time 最大的不足是这里没有本地化的周相关字段。两种字段实现设计的一个共同特点是两者都基于 long 类型的值(没有其他类型,甚至没有枚举)。

枚举

JSR-310 提供类似or的枚举,而 Joda-Time 不提供此功能,因为它主要是在Java 5之前的 2002-2004 年开发的。DayOfWeekMonth

区域 API

a) JSR-310 提供比 Joda-Time 更多的时区功能。后者无法以编程方式访问时区偏移转换的历史,而 JSR-310 能够做到这一点。

b) 供您参考:JSR-310 已将其内部时区存储库移动到新位置和不同格式。旧的库文件夹 lib/zi 不再存在。

调节器与财产

JSR-310 引入了TemporalAdjuster-interface 作为一种形式化的方式来外部化时间计算和操作,特别是对于库或框架编写者来说,这是嵌入 JSR-310 新扩展的一种不错且相对简单的方法(一种等效于静态助手前者的课程java.util.Date)。

然而,对于大多数用户而言,此功能的价值非常有限,因为编写代码的负担仍然在用户身上。基于新概念的内置解决方案TemporalAdjuster并不多,目前只有辅助类TemporalAdjusters具有有限的操作集(以及枚举Month或其他时间类型)。

Joda-Time 提供了一个 field-package,但实践表明,新的 field 实现很难编码。另一方面,Joda-Time 提供了所谓的属性,这些属性使得一些操作比 JSR-310 中的更容易和更优雅,例如property.withMaximumValue()

日历系统

JSR-310 提供 4 个额外的日历系统。最有趣的是Umalqura(在沙特阿拉伯使用)。其他 3 个是:民国(台湾)、日本(自 1871 年以来只有现代历法!)和泰国佛教(仅在 1940 年之后才正确)。

Joda-Time 提供基于计算器的伊斯兰日历,而不是像 Umalqura 这样的基于目击的日历。Joda-Time 也以类似的形式提供 Thai-Buddhist,但 Minguo 和日本的则没有。否则,Joda-Time 也提供科普特和埃塞俄比亚日历(但不支持任何国际化)。

对欧洲人来说更有趣的是:Joda-Time 还提供公历儒略历和混合公历-儒略历。但是,实际历史计算的实用价值是有限的,因为根本不支持日期历史中不同年份开始等重要特征(同样的批评对 old 有效java.util.GregorianCalendar)。

两个图书馆都完全没有其他日历,如希伯来语波斯语印度教。

时代天数

JSR-310 有JulianFields类,而 Joda-Time(2.0 版)在DateTimeUtils类中提供了一些辅助方法。

时钟

JSR-310 没有接口(设计错误),但有一个抽象类java.time.Clock,可用于任何时钟依赖注入。Joda-Time在DateTimeUtils中提供了MillisProvider接口和一些辅助方法。所以这种方式 Joda-Time 也能够支持具有不同时钟(模拟等)的测试驱动模型。

持续时间算术

这两个库都支持以一个或多个时间单位计算时间距离。但是,在处理单单元持续时间时,JSR-310 样式显然更好(并且基于 long 而不是使用 int):

JSR-310 =>long days = ChronoUnit.DAYS.between(date1, date2);

乔达时间 =>int days = DAYS.daysBetween(date1, date2).getDays();

对多单元持续时间的处理也不同。甚至计算结果也可能不同 - 请参阅此已关闭的 Joda-Time 问题。虽然 JSR-310 使用一种非常简单且有限的方法来仅使用类Period(基于年、月和日的持续时间)和Duration(基于秒和纳秒),但 Joda-Time 使用更复杂的方法使用类PeriodType来控制应以哪个单位表示持续时间(Joda-Time 称之为“周期”)。虽然PeriodType-API 使用 JSR-310 根本不提供的类似方式有点尴尬。特别是在 JSR-310 中还不能定义混合的日期和时间持续时间(例如,基于天和小时)。因此,如果涉及从一个库迁移到另一个库,请注意。讨论中的库是不兼容的——尽管类名部分相同。

间隔

JSR-310 不支持此功能,而 Joda-Time 的支持有限。另请参阅此SO-answer

格式化和解析

比较这两个库的最佳方法是查看同名类DateTimeFormatterBuilder (JSR-310) 和DateTimeFormatterBuilder (Joda-Time)。JSR-310 变体更强大一些(也可以处理任何类型TemporalField的字段实现者已经设法编写了一些扩展点,如resolve())。然而,最重要的区别是 - 在我看来:

JSR-310 可以更好地解析时区名称(格式模式符号 z),而 Joda-Time 在其早期版本中根本无法做到这一点,现在只能以非常有限的方式。

JSR-310 的另一个优点是支持独立的月份名称,这在俄语或波兰语等语言中很重要。Joda-Time无法访问这些资源——即使在 Java-8 平台上也是如此。

JSR-310 中的模式语法也比 Joda-Time 更灵活,允许可选部分(使用方括号),更面向 CLDR 标准并提供填充(字母符号 p)和更多字段。

否则,应注意 Joda-Time 可以使用PeriodFormatter格式化持续时间。JSR-310 无法做到这一点。


希望这个概述有所帮助。所有收集到的信息主要是由于我的努力和调查如何设计和实施更好的日期和时间库(没有什么是完美的)。

2015 年 6 月 24 日更新:

同时,我有时间为 Java 中的不同时间库编写和发布表格概述。这些表还包含 Joda-Time v2.8.1 和 Java-8 (JSR-310) 之间的比较。比这个帖子更详细。

于 2014-07-08T15:20:43.547 回答
44

Java 8 日期/时间:

  1. Java 8 类是围绕人类时间构建的。它使它们快速用于人类日期时间算术/转换。
  2. 日期/时间组件 gettergetDayOfMonth在 Java 8 实现中具有 O(1) 复杂度。
  3. 由于在 JDK 内部抛出和捕获异常,Java 8 ea b121中的OffsetDateTime//解析非常慢。OffsetTimeZonedDateTime
  4. 一组包:java.time.*, java.time.chrono.*, java.time.format.*, java.time.temporal.*,java.time.zone.*
  5. 瞬间(时间戳) 日期和时间 部分日期和时间 解析器和格式化程序 时区 不同的年表(日历)。
  6. 现有的类有问题,比如 Date 不支持 I18N 或 L10N。它们是可变的!
  7. 更简单、更健壮。
  8. 可以注入时钟。
  9. 可以使用各种属性创建时钟 - 静态时钟、模拟时钟、低精度时钟(整秒、整分钟等)。
  10. 可以使用特定时区创建时钟。Clock.system(Zone.of("America/Los_Angeles")).
  11. 使代码处理日期和时间可测试。
  12. 使测试独立于时区。

乔达时间:

  1. Joda-Time 在内部使用机器时间。基于 int/long 值的手动实现会快得多。
  2. Joda-Time getter 需要在每次 getter 调用时进行计算机到人的时间计算,这使得 Joda-Time 在这种情况下成为瓶颈。
  3. 它由不可变的类组成,它处理即时、日期和时间、部分和持续时间它很灵活它设计得很好。
  4. 将日期表示为瞬间。但是一个日期和时间可能对应多个瞬间。夏令时结束时的重叠小时。以及根本没有任何与之对应的瞬间。白天开始时的间隔时间。必须为简单的操作执行复杂的计算。
  5. 在其大多数方法中接受空值作为有效值。导致微妙的错误。

有关更详细的比较,请参见:-

Java 8 日期/时间库性能(以及 Joda-Time 2.3 和 juCalendar)。& Java 8 中的新日期和时间 API

于 2014-07-08T13:35:36.007 回答
11

Joda-Time 现在处于维护模式

不是对这个问题的直接回答,但Joda-Time项目不再处于积极开发中。该团队建议用户迁移到更新的java.time API。请参阅Oracle 的教程

从官方GitHub项目页面:

Joda-time 不再处于积极开发中,除了保持时区数据是最新的。从 Java SE 8 开始,用户被要求迁移到 java.time (JSR-310) - JDK 的核心部分,它取代了这个项目。对于 Android 用户,在 API 26+ 中添加了 java.time。需要支持较低 API 级别的项目可以使用 ThreeTenABP 库。

于 2020-06-06T17:24:16.400 回答
1

该项目由 Joda-Time (Stephen Colebourne) 的作者和 Oracle 在 JSR 310 下联合领导,并将出现在新的 Java SE 8 包 java.time 中。

https://www.oracle.com/technical-resources/articles/java/jf14-date-time.html

于 2021-06-26T07:03:58.330 回答