【问题标题】:Should I use java.util.Date or switch to java.time.LocalDate我应该使用 java.util.Date 还是切换到 java.time.LocalDate
【发布时间】:2015-04-28 02:28:21
【问题描述】:

编辑:嗯,显然它过于基于意见,所以让我尝试更准确地重新措辞 -

在不需要任何向后兼容性的 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 没有明确的答案。

谢谢。

【问题讨论】:

标签: java date jdbc


【解决方案1】:

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

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

  • 更简单的格式/解析。 API 有自己的格式/解析方法
  • API 包括加法/减法运算(minusMinutesplusDays 等)

以上都不在java.util.Date

Old Date 也可以像这样转换为LocalDateTime

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

【讨论】:

  • 那么在你看来,是时候放弃旧的 Date 了吗?
  • @ShedomWei 这完全取决于您的项目要求。 OP 决定坚持使用旧日期,因为“显然 MySQL 连接器 J 不支持 Java 8”(2015 年 3 月 3 日意大利 0:40)。
【解决方案2】:

我正在添加到correct Answer by Ole V.V.

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 driver 可能会也可能不会添加对这些的支持。

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

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

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

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

要适应 UTC,请提取 Instant。根据定义,Instant 始终采用 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. 

注意naming convention used in java.timeatfromtowith,等等。


关于java.time

java.time 框架内置于 Java 8 及更高版本中。这些类取代了麻烦的旧 legacy 日期时间类,例如 java.util.DateCalendarSimpleDateFormat

要了解更多信息,请参阅Oracle Tutorial。并在 Stack Overflow 上搜索许多示例和解释。规格为JSR 310

Joda-Time 项目现在位于maintenance mode,建议迁移到java.time 类。

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

从哪里获得 java.time 类?

ThreeTen-Extra 项目通过附加类扩展了 java.time。该项目是未来可能添加到 java.time 的试验场。您可以在这里找到一些有用的类,例如IntervalYearWeekYearQuartermore

【讨论】:

  • ThreeTenBackport 是一个很好的库,但现在对于 Android (2021 年及之后)official documents 和 JakeWharton(ThreeTen 的作者)建议使用 Java 8+ API 去糖支持。
【解决方案3】:

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

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

唯一可以简单考虑的,就是你已经排除的那个。

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

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

Java 6 和 7:称重

如果您使用的是 Java 6 或 7,则需要将 ThreeTen-Backport 用于 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 使用模式不可变对象工厂方法,这与大多数旧类不同。

【讨论】:

    猜你喜欢
    • 2015-01-30
    • 2014-02-10
    • 1970-01-01
    • 1970-01-01
    • 2018-10-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多