共同特征
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 中的一些类(例如ChronoField和WeekFields)给出,而 Joda-Time 在这方面相当薄弱 - 请参阅DateTimeFieldType。Joda-Time 最大的不足是这里没有本地化的周相关字段。两种字段实现设计的一个共同特点是两者都基于 long 类型的值(没有其他类型,甚至没有枚举)。
枚举
JSR-310 提供类似or的枚举,而 Joda-Time 不提供此功能,因为它主要是在Java 5之前的 2002-2004 年开发的。DayOfWeek
Month
区域 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) 之间的比较。比这个帖子更详细。