我应该使用java.util.Date还是切换到java.time.LocalDate


74

编辑:嗯,显然这太基于观点了,所以让我尝试更精确地改写它-

在不需要向后兼容性的Java代码中使用LocalDate,LocalTime等是否有明显的警告或缺点,如果需要,它们是什么?

我正在寻找诸如“当前EE库X和Y无法与LocalDate一起正常工作”或“此非常有用的模式被LocalTime破坏”之类的问题。


(这是原始问题供参考)

在Java 8中,引入了新的时间API,即java.time.LocalDate等,但未将java.util.Date标记为已弃用。

我正在编写一个新项目,该项目不需要向后兼容。我应该只使用LocalDate,LocalDateTime等吗?与良好的旧java.util.Date相比,使用此新API有什么缺点吗?

特别是-我将主要使用JDBC。从我所看到的,JDBC可以很好地处理java.util.Date。它也适合LocalDate吗?

搜索产生了大量站点,这些站点告诉您如何从一种格式转换为另一种格式,但是对于新代码是否应使用旧API却没有明确的答案。

谢谢。


10
good old java.util.Date-很旧,但是不好。新代码应使用新的API。
伊利亚Bursov

7
有一个原因创建了一个全新的日期API。如果您有未开发的项目,请使用Java 8引入的API。
Jeroen Vannevel 2015年

1
请使用新的API。:-P
Paul Vargas

3
Java乐于使用@Deprecated批注来处理不好但不会被删除的事情。
Louis Wasserman

3
Oracle自己的文档给出了不赞成使用API​​的三个主要原因:“它不安全,有bug或效率很低;在将来的版本中将不复存在;它会鼓励不良的编码实践。” 这些是否适用于java.util.Date可能是一个问题。
MarsAtomic

Answers:


54

尽管有名称,但java.util.Date可以用于存储日期和时间(它存储自纪元以来的UTC毫秒偏移量)

由于功能强大,我肯定会使用新的API:

  • 格式/解析更容易。API具有自己的格式/解析方法
  • 该API包括加/减运算(minusMinutes,plusDays等)

以上都不可用在java.util.Date上

还可以将旧日期转换为LocalDateTime,如下所示:

Date oldDate = ...
LocalDateTime newDateTime = 
  LocalDateTime.from(Instant.ofEpochMilli(oldDate.getTime()));

2
因此,根据您的意见,是时候完全丢弃旧的Date了吗?
Shedom Wei

@ShedomWei这完全取决于您的项目要求。OP决定坚持使用旧的Date,因为“显然MySQL连接器J不支持Java 8”(Itai I 3 Mar 3 '15 at 0:40)。
斯蒂芬

15

我要添加到Ole VV正确答案中

JDBC 4.2

特别是-我将主要使用JDBC。

JDBC 4.2添加了对与数据库交换java.time对象的支持。请参见 PreparedStatement::setObjectResultSet::getObject方法。

ZoneId z = ZoneId.of( "Africa/Tunis" ) ;
LocalDate today = LocalDate.now( z ) ;
myPreparedStatement.setObject( … , today ) ;

恢复。

LocalDate ld = myResultSet.getObject( … , LocalDate.class ) ;

对于逃避我的原因,JDBC规范并没有要求对两种最常用的类支持:InstantZonedDateTime。您的数据库和JDBC驱动程序可能会也可能不会添加对它们的支持。

如果没有,您可以轻松转换。从开始OffsetDateTime,在JDBC中需要支持。

OffsetDateTime odt = myResultSet.getObject( … , OffsetDateTime.class ) ;

要通过特定区域(时区)的人们使用的挂钟时间来查看这一刻,请应用ZoneId来获取ZonedDateTime对象。

ZoneId z = ZoneId.of( "Asia/Kolkata" ) ;
ZonedDateTime zdt = odt.atZoneSameInstant() ;

要调整为UTC,请提取一个Instant。根据Instant定义,An始终使用UTC。

Instant instant = odt.toInstant() ;

您可以转换为另一种方式,以写入数据库。

myPreparedStatement.setObject( … , zdt.toOffsetDateTime() ;  // Converting from `ZonedDateTime` to `OffsetDateTime`. Same moment, same point on the timeline, different wall-clock time.

…和:

myPreparedStatement.setObject( … , instant.atOffset( ZoneOffset.UTC ) ) ;  // Converting from `Instant` to `OffsetDateTime`. Same moment, same point on the timeline, and even the same offset. `OffsetDateTime` is a more flexible class with abilities such as (a) applying various offsets and (b) flexible formatting when generating text, while `Instant` is meant to be a more basic building-block class. 

注意所使用的命名约定java.timeatfromtowith,等。

Java(现代和旧式)和标准SQL中的日期时间类型表。


关于java.time

java.time框架是建立在Java 8和更高版本。这些类取代麻烦的老传统日期时间类,如java.util.DateCalendar,和SimpleDateFormat

要了解更多信息,请参见Oracle教程。并在Stack Overflow中搜索许多示例和说明。规格为JSR 310

现在处于维护模式Joda-Time项目建议迁移到java.time类。

您可以直接与数据库交换java.time对象。使用与JDBC 4.2或更高版本兼容的JDBC驱动程序。不需要字符串,不需要类。java.sql.*

在哪里获取java.time类?

ThreeTen-额外项目与其他类扩展java.time。该项目为将来可能在java.time中添加内容打下了基础。你可能在这里找到一些有用的类,比如IntervalYearWeekYearQuarter,和更多


1

Java 8及更高版本:不用担心

不,如果您使用的是Java 8或更高版本(内置Java),则没有理由不希望使用现代的Java日期和时间API java.time。

可能要简要考虑的唯一一件事就是您已经排除的那件事。

我正在编写一个新项目,该项目不需要向后兼容。

即使是向后兼容,您也可以安全地使用java.time,因为转换方法已内置在Java 8的旧类中。

Java 6和7:权衡

如果您使用的是Java 6或7,则需要使用ThreeTen- Backport for java.time,在ThreeTenABP中的API级别26以下进一步适应Android 。如果您仅执行很少的非常简单的日期和时间工作,并且以某种方式不存在前向兼容性,则可以考虑外部依赖是否值得。请注意,您的外部依赖关系只是Java 8及更高版本内置的依赖项,因此坚如磐石,因此,仅在迁移到Java 8或更高版本之前才需要它。在那时,您可以更改导入,重新测试并取消反向端口。

您的负债示例

当前的EE库X和Y无法与LocalDate一起正常使用

有一些例子,还有JDK中的库类。我的选择是在自己的代码中使用java.time,并且仅在调用尚未接受java.time类型的API之前进行转换。相反,如果我从API获取过时类的实例,请先将其转换,然后使用java.time进行其余操作。

LocalTime打破了这个非常有用的模式

我不知道有这种模式。相反,与大多数旧类相反,java.time使用模式不可变对象工厂方法

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.