Java 8日期时间API(java.time)与Joda-Time之间的区别


264

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

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

  • Joda-Time无法做到的java.time可以做什么?
  • java.time比Joda-Time有什么优势?
  • java.time的性能更好吗?

8
并非如此,这与Java 7有关,与Java 8不相关。针对该问题的答案是针对Java 8编辑的,非常少的细节。我的问题特别是询问Java 8的新DateTime API,而不是Java 7的java.util.Date。我只是在寻找将Java 8与JodaTime进行比较的答案。
扎克2014年

2
也许此Oracle文档可以为您提供帮助。
MarioDS 2014年

如果您具有Java 7,请使用其他库;如果您具有Java 8,请使用内置库。由于这两个库基本上都是由同一人设计的,所以我不确定您期望什么主要差异。
彼得·劳瑞

2
@PeterLawrey:Joda-Time和Java 8日期和时间API实际上是完全不同的。
jarnbjo 2014年

5
您还可以阅读两个项目的主要作者Stephen Colbourne的博客文章
Matt Johnson-Pint 2014年

Answers:


416

共同特征

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,后者根本不是类型安全的)。

性能

请参阅@ OO7的其他答案,其中指出了对Mikhail Vorontsov的分析,尽管第3点(异常捕获)可能已过时-请参见此JDK-bug。不同的性能(通常对JSR-310有利)主要是由于Joda-Time的内部实现始终使用类似于机器时间的长原语(毫秒)。

空值

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

精确

JSR-310的处理精度为纳秒级,而Joda-Time的精度为毫秒级

支持的字段:

临时包中的某些类(例如ChronoFieldWeekFields)给出了有关Java-8(JSR-310)中受支持字段的概述,而Joda-Time在该领域则很弱-请参见DateTimeFieldType。Joda-Time的最大不足是这里没有与星期相关的本地化字段。这两个字段实现设计的一个共同特征是,它们都基于long类型的值(没有其他类型,甚至没有枚举)。

枚举

JSR-310提供像这样的枚举DayOfWeekMonth而Joda-Time不提供这样的枚举,因为它主要是在2002年至2004年间Java 5之前开发的。

区域API

a)JSR-310提供了比Joda-Time更多的时区功能。后一种方法无法通过编程访问时区偏移量的历史记录,而JSR-310可以做到这一点。

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

调节器与属性

JSR-310引入了TemporalAdjuster-interface作为将时间计算和操作外部化的一种形式化方法,尤其是对于库或框架编写者而言,这是一种嵌入JSR-310新扩展的好方法,并且相对简单(一种等效于静态助手的方法)前者的类java.util.Date)。

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

Joda-Time提供了一个现场程序包,但实践表明,新的现场实现很难编写代码。另一方面,Joda-Time提供了所谓的属性,这些属性使某些操作比JSR-310中的操作更轻松,更优雅,例如property.withMaximumValue()

日历系统

JSR-310提供了4个额外的日历系统。最有趣的是Umalqura(在沙特阿拉伯使用)。其他三个是:Miningo(台湾),日语(仅是1871年以来的现代日历!)和ThaiBuddhist(仅在1940年之后正确)。

Joda-Time提供基于计算器基础的伊斯兰日历,而不是像Umalqura这样基于目击的日历。乔达时报(Joda-Time)也以类似的方式提供泰国佛教徒,但Mininguo和日本人都没有。否则,Joda-Time还提供科普特和埃塞俄比亚历法(但不支持任何国际化)。

对于欧洲人来说更有趣:Joda-Time还提供了公历儒略历公历与儒混合历。但是,由于根本不支持诸如日期历史中不同的年份开始之类的重要功能,因此实际历史计算的实用价值受到限制(同样的批评对老有效java.util.GregorianCalendar)。

两个库中都完全缺少希伯来语波斯语印度等其他日历。

大纪元

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

钟表

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

持续时间算术

这两个库都支持以一个或多个时间单位的时间距离计算。但是,在处理单一单位持续时间时,JSR-310样式显然更好(并且是基于长型的,而不是使用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称之为“ Period”)。而PeriodTypeJSR-310根本不提供-API以某种方式很难使用类似的方式。特别是在JSR-310中,尚不可能定义混合的日期和持续时间(例如,基于天和小时)。因此,如果涉及从一个库到另一个库的迁移,请注意。讨论中的库不兼容-尽管类名部分相同。

间隔

当Joda-Time支持有限时,JSR-310不支持此功能。另请参阅此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-06-24更新:

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


12
这是一个出色的职位。非常感谢您分享所有这些信息。如果在Joda和JSR-310之间选择(仅适用于普通用例),您会选择哪一个?我现在正面临这种选择。我之所以考虑使用JSR-310,只是因为它是更新的,并且我尽可能地支持“向前发展”。
kevinarpe

7
@kevinarpe如果我只能在JSR-310和Joda-Time之间进行选择,我可能会更喜欢JSR-310,因为Joda-Time几乎停止了任何进一步的开发(不能期望会有新的重大功能-只是错误修复和小的更新)。而且JSR-310的设计更加现代化(并且具有更好的内部质量)。顺便说一句,不过,我的真正决定是选择我自己的Time4J库-另请参阅文章底部给出的表格概述的链接。拥有替代方法总是一件好事,并且在很大程度上取决于您所需的功能。
Meno Hochschild 2015年

持续时间不是Java8的Interval版本吗?
Christian Hujer '16

1
@ChristianHujer否,java.time.Duration无法查询其开始或结束,这与锚定在时间线上的时间间隔相反。自未知启动以来,这种JSR-310型仅经过了几秒和十亿分之一秒。
Meno Hochschild

42

Java 8日期/时间:

  1. Java 8类是围绕人类时间构建的。它使它们可以快速进行人类日期时间算术/转换。
  2. 诸如日期/时间组件的获取器getDayOfMonth在Java 8实现中具有O(1)复杂性。
  3. 解析OffsetDateTime/ OffsetTime/ ZonedDateTime是Java 8 EA B121非常缓慢,由于在JDK抛出和捕获内部例外。
  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吸气剂需要在每次吸气剂调用时进行计算机到人的时间计算,这使Joda-Time在这种情况下成为瓶颈。
  3. 它由不可变的类组成,它处理瞬时,日期和时间,部分和持续时间。它非常灵活。
  4. 将日期表示为瞬间。但是日期和时间可能对应一个以上的瞬间。夏令时结束时的重叠时间。以及完全没有对应的瞬间。白天开始的间隔时间。必须执行复杂的计算才能执行简单的操作。
  5. 接受null作为大多数方法的有效值。导致细微的错误。

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

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


当您说“使测试独立于时区时”。那是什么意思?
扎克2014年

@Zack:可能是,如果您测试的代码根据时区的不同而有所不同,则可能需要您强制测试以与操作系统提供的默认时区不同的默认时间运行。
jarnbjo 2014年

哈-我以为你说的是​​乔达在内部运行时间机器而不是机器时间...而且我不会感到惊讶
Kyranstar 2014年

4
@ OO7您是什么意思“人类时间”?无论如何,时间是由机器计算的。
IgorGanapolsky

1

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.