tl;博士
( (GregorianCalendar) customerSearch.get( "DateOfBirth" ) ) // Retrieve and cast object of legacy class `GregorianCalendar`.
.toZonedDateTime() // Convert from terrible legacy class to modern *java.time* class.
.toLocalDate() // Extract the date-only portion, omitting time-of-day and time zone.
java.time
您正在使用并且可能滥用了可怕的日期时间类,这些类在几年前被 JSR 310 定义的 java.time 类所取代。
-
ZonedDateTime 替换 GregorianCalendar
-
Instant 替换 java.util.Date
-
LocalDate 替换 java.sql.Date
如果您必须与尚未更新到java.time 的旧代码进行互操作,则可以来回转换。调用添加到旧类的新转换方法。
GregorianCalendar gc = customerSearch… ;
ZonedDateTime zdt = gt.toZonedDateTime() ;
如果您只想要没有时间和时区的日期,请提取LocalDate。
LocalDate dateOfBirth = zdt.toLocalDate() ;
如果 Date 是指 java.sql.Date 类,则应使用上述行而不是使用 LocalDate。
如果Date 是指java.util.Date,那将是错误的类。该类代表 UTC 中的一个时刻。通过将 GregorianCalendar/ZonedDateTime 中的分区时刻调整为 UTC,您可能会更改日期。
转换
如果您需要一个java.util.Date 对象来与尚未针对java.time 更新的旧代码进行互操作,您可以进行转换。 java.util.Date 代表 UTC 中的时刻,因此我们需要 java.time 中的等价物 Instant,这也是 UTC 中的时刻,但分辨率更精细,为纳秒而不是毫秒。
我们可以从上面看到的ZonedDateTime 中提取一个Instant。实际上,这只是从分区值调整为 UTC 值。同一时刻,时间轴上的同一点,不同的挂钟时间。
Instant instant = zdt.toInstant() ; // Extract a `Instant`, adjusting from zone to UTC.
在旧类上使用新的转换方法。
java.util.Date myJavaUtilDate = java.util.Date.from( instant ) ; // Beware of possible data-loss in the fractional second, truncating from nanos to millis.
如果您需要另辟蹊径,从传统到现代。
Instant instant = myJavaUtilDate.toInstant() ;
使用适当的类型
如果您尝试表示出生日期,通常只使用没有时间和区域的日期,然后在地图中使用LocalDate。 GregorianCalendar、java.util.Date 和 ZonedDateTime 类都代表一个时刻,时间线上的一个特定点。它们不应该仅用于日期。
java.sql.Date 类 假装 是一个仅限日期的类,但是通过一个糟糕的设计决策,作为 java.util.Date 的子类,实际上确实带有时间和偏移量/区域.如上所述,该类已替换为LocalDate。
普通日期对象
java.util.Date 或 java.sql.Date 没有什么比任何其他日期时间类更“正常”的了。
-
java.util.Date 代表 UTC 中的一个时刻,始终是 UTC,尽管它设计得非常糟糕的 toString 方法告诉你(谎言)。当您需要 UTC 时间时,请改用 java.time.Instant。
-
java.sql.Date 仅表示日期,但正如所讨论的,实际上在内部带有时间和区域/偏移量。请改用java.time.LocalDate 来表示日期而不是时刻。
-
GregorianCalendar 代表特定地区(时区)的人们使用的挂钟时间中看到的时刻。为此,请改用 ZonedDateTime。
-
java.sql.Timestamp 代表 UTC 中的一个时刻,但分辨率更精细,为纳秒而不是毫秒。 java.time 中所有与时刻相关的类都使用纳秒级的分辨率。因此,在 UTC 分辨率为 UTC 的情况下,请使用 java.time.Instant 而不是 Timestamp。
从 JDBC 4.2 开始,我们可以直接与数据库交换 java.time 类。因此,您的数据库工作无需再次触碰java.sql.Date 或java.sql.Timestamp。
关于java.time
java.time 框架内置于 Java 8 及更高版本中。这些类取代了麻烦的旧 legacy 日期时间类,例如 java.util.Date、Calendar 和 SimpleDateFormat。
Joda-Time 项目现在位于maintenance mode,建议迁移到java.time 类。
要了解更多信息,请参阅Oracle Tutorial。并在 Stack Overflow 上搜索许多示例和解释。规格为JSR 310。
您可以直接与您的数据库交换 java.time 对象。使用符合JDBC 4.2 或更高版本的JDBC driver。不需要字符串,不需要java.sql.* 类。
从哪里获得 java.time 类?
ThreeTen-Extra 项目通过附加类扩展了 java.time。该项目是未来可能添加到 java.time 的试验场。您可以在这里找到一些有用的类,例如Interval、YearWeek、YearQuarter 和more。