从Joda时间库迁移到Java时间库(Java 8)

11

我们的软件架构师决定从我们项目的依赖项中删除Joda时间库,并使用Java 8时间的功能。我正在研究我们的项目,试图找到我们使用Joda时间库的所有位置,并确定我们实际上正在使用什么(如joda LocalDateDateTime等)。 我不是Joda时间库的专家,也不是Java 8时间的专家,所以我有一些问题: 在代码中,我看到了很多像这样的地方:

DateTime jodaDateTime = new DateTime();
doSomething(jodaDateTime.toDate()); 

我有点困惑。

(Q1) 在这种情况下使用joda DateTime 有意义吗? 我认为我们可以只使用经典的java.util.Date而不需要Joda:

java.util.Date date = new Date();
doSomething(date);

正确吗?

另外,我看到了这段代码:

org.joda.time.DateTime jodaDateTime = new DateTime();
org.joda.time.DateTime jodaDateTimeInPast = jodaDateTime.minusSeconds(60);
doSomething(jodaDateTimeInPast.toDate());

我认为Java 8时间API提供了很好的支持来计算过去的任何日期,所以我有一个想法,可以将上面的代码替换为Java 8:

LocalDatetime java8DateTime = LocalDateTime.now();
LocaldateTime java8DateTimeInPast = java8DateTime.minusSeconds(60);
Date java8Date = Date.from(java8DateTimeInPast.atZone(ZoneId.systemDefault()).toInstant());
doSomething(java8Date);

(Q2) 我是否以正确的方式完成了它?我不确定百分之百。 我只是在这个链接中找到了一个表格: "Converting from Joda-Time to java.time" 在那里我找到了信息,我需要使用java.time.ZonedDateTimejava.time.OffsetDateTime类,而不是java.time.LocalDateTime,因为LocalDateTime -

相同的概念-没有时区的日期和时间

请确认我的重构是正确的(对于Q1Q2)。

2个回答

11

关于转换的大多数问题应该在我关于这方面的博客中解决。

Q1a: 创建Joda-Time对象只为了转换回java.util.Date是没有意义的。但是,该方法可能应该采用InstantZonedDateTime

Instant instant = Instant.now();
doSomething(instant);  // method changed to take Instant

请注意,Instant 是与 java.util.Date 最接近的匹配项。

Q1b: 这种情况涉及到时区,因此应该使用 ZonedDateTime

ZonedDateTime java8DateTime = ZonedDateTime.now();  // uses ZoneId.systemDefault()
ZonedDateTime java8DateTimeInPast = java8DateTime.minusSeconds(60);
doSomething(java8DateTimeInPast.toInstant());

假设 doSomething 已经被修改以接收一个 Instant 作为参数。

使用 java.time 的关键是考虑每个数据元素应该使用哪种数据类型:

  • 仅需要日期?使用 LocalDate
  • 仅需要时间?使用 LocalTime
  • 需要日期、时间和时区?使用 ZonedDateTime
  • 仅需要时间戳而无其他信息?使用 Instant
  • 需要带有偏移量的网络日期-时间格式(不是时区)?使用 OffsetDateTime

你写道:“Instant是与java.util.Date最接近的匹配项”,但例如:new Date().toString()返回:Thu Jan 28 18:26:27 EET 2016,而Instant.now().toString()返回:2016-01-28T16:26:27.210Z。正如你所看到的,Instant返回的是UTC的16:26:27,而Date返回的是EET的18:26:27。 - user471011
5
java.util.DatetoString() 方法返回本地时区的时间,但对象的状态不包含该信息。理解这个差异是理解 java.util.Date 的关键。 - JodaStephen

2
您的做法对两种情况都是正确的。我可能要补充一点,即Java 8时间取代了java.util.Date,因此您可能需要考虑用doSomething(java.time.temporal.TemporalAccessor)替换doSomething(java.util.Date)方法。但是,java.util.Date尚未被宣布过时,所以您不必担心。根据我的经验,Java 8时间包是非常灵活和全面的包。即使Joda在其时间也是一个好的包,但我还是发现了一些有趣的错误。

4
大多数应用程序代码不应使用TemporalAccessor。一般来说,如果你在低级库之外使用它,那么你正在做错误的事情。在这种情况下,应该使用doSomething(Instant)doSomething(ZonedDateTime)或类似方法。 - JodaStephen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接