Java 8 Date Time API(java.time)和Joda-Time之间的差异

Zac*_*ack 258 java datetime jodatime java-8 java-time

我知道有关于java.util.Date和Joda-Time的问题.但经过一番挖掘后,我找不到关于java.time API(Java 8中新增,JSR 310定义)和Joda-Time之间差异的线程.

我听说Java 8的java.time API比Joda-Time更清洁,可以做得更多.但我找不到比较两者的例子.

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

Men*_*ild 404

共同特征

a)两个库都使用不可变类型.Joda-Time还提供其他可变类型MutableDateTime.

b)此外:这两个图书馆的灵感来自Eric Evans的设计研究"TimeAndMoney"Martin Fowler关于领域驱动风格的想法,因此他们或多或少地努力获得流畅的编程风格(尽管并不总是完美的;-)).

c)对于这两个库,我们得到一个真实的日历日期类型(称为LocalDate),一个真正的墙上时间类型(称为LocalTime)和组合(称为LocalDateTime).这是旧的相比有非常大的胜利java.util.Calendarjava.util.Date.

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

性能

请参阅@ OO7指向Mikhail Vorontsov分析的其他答案,尽管第3点(异常捕获)可能已经过时 - 请参阅此JDK错误.不同的性能(一般支持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提供类似或者Joda-Time不提供这种内容的枚举,因为它主要是在Java 5之前的2002-2004年开发的.DayOfWeekMonth

Zone API

a)JSR-310提供比Joda-Time更多的时区功能.当JSR-310能够执行此操作时,后者无法以编程方式访问时区偏移转换的历史记录.

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

调整员与财产

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

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

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

日历系统

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

Joda-Time提供基于计算基础的伊斯兰历法 - 而不是像Umalqura那样的基于目击的日历.Joda-Time也以类似的形式提供泰国佛教徒,Minguo和日本人没有.否则Joda-Time也提供科普特和ethiopic日历(但没有任何国际化支持).

对于欧洲人来说更有趣:Joda-Time还提供Gregorian,Julian和混合格里高利 - 朱利安历法.然而,实际历史计算的实际价值是有限的,因为根本不支持日期历史中不同年份开始的重要特征(相同的批评对旧的有效java.util.GregorianCalendar).

其他日历,如希伯来语,波斯语印度语,在两个图书馆都完全缺失.

大纪元

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

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

持续时间算术

两个库都支持以一个或多个时间单位计算时间距离.但是,当处理单个单位持续时间时,JSR-310风格显然更好(并且基于长期而不是使用int):

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

Joda-Time => int days = DAYS.daysBetween(date1, date2).getDays();

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

间隔

JSD-310不支持此功能,而Joda-Time支持有限.另见这个SO答案.

格式化和解析

比较两个库的最佳方法是查看等同命名的类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-06-24更新:

与此同时,我找到了编写和发布 Java中不同时间库的表格概述的时间.这些表还包含Joda-Time v2.8.1和Java-8(JSR-310)之间的比较.它比这篇文章更详细.

  • 这是一篇优秀的文章.非常感谢分享所有这些信息.如果在Joda和JSR-310之间做出选择(仅适用于香草用例),您会选择哪种?我现在面对这个选择.我正在考虑JSR-310,只是因为它更新,我试图尽可能地支持"前进". (10认同)
  • @kevinarpe如果我只有JSR-310和Joda-Time之间的选择我可能更喜欢JSR-310,因为Joda-Time几乎停止了任何进一步的开发(不能期望新的大功能 - 只是错误修正和小更新).JSR-310的设计更加现代(并且具有更好的内部质量).顺便说一句,并不奇怪,我真正的决定是宁愿选择我自己的库Time4J - 另请参阅我帖子底部给出的表格概述的链接.拥有替代品总是好的,它在很大程度上取决于您需要什么功能. (7认同)

OO7*_*OO7 41

Java 8日期/时间:

  1. Java 8类是围绕人类时代构建的.它使它们快速进行人类日期算术/转换.
  2. 日期/时间组件getter getDayOfMonth在Java 8实现中具有O(1)复杂性.
  3. 由于在JDK内部抛出和捕获的异常,Java 8 ea b121中的OffsetDateTime/ OffsetTime/ 解析ZonedDateTime速度非常慢.
  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. 使测试独立于时区.

Joda-Time:

  1. Joda-Time正在使用机器时间.基于int/long值的手动实现会快得多.
  2. Joda-Time getters需要在每次getter调用时进行计算机到人的时间计算,这使得Joda-Time成为这种情况下的瓶颈.
  3. 它由不可变的类组成,它处理Instants,Date&Time,Partials和Durations它很灵活它设计得很好.
  4. 将日期表示为瞬间.但是日期和时间可能对应不止一个瞬间.夏令时结束时的重叠时间.并且根本没有任何对应的瞬间.白天开始时的间隙时间.必须为简单的操作执行复杂的计算.
  5. 在大多数方法上接受null作为有效值.导致微妙的错误.

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

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

  • @ OO7你的意思是'人类时间'?无论如何,时间由机器计算. (3认同)

Sai*_*pta 9

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 库。