【问题标题】:Gregorian Date to Date公历日期至今
【发布时间】:2019-06-21 14:38:49
【问题描述】:

这应该很简单

customerSearch.get("DateOfBirth") 其中 customerSearch 是 HashMap<String, Object>,它是公历日期。

但我需要一个普通的Date 对象。

我试过了

Date dateOfBirth = new Date(
        ((GregorianCalendar) customerSearch.get("DateOfBirth")).getTimeInMillis());

但不能将公历日期转换为日期。

有什么帮助吗?

【问题讨论】:

  • 你为什么要和GregorianCalendarDate打架?这些课程设计不良且早已过时。恕我直言,没有人应该在 2019 年使用它们。而是使用来自java.time, the modern Java date and time APILocalDate
  • 我无法复制。您的代码在我的 Java 8 上运行良好,并且在一次运行中产生了 DateWed Dec 29 00:00:00 UTC 1999How to create a Minimal, Complete, and Verifiable example,请。
  • @ErayBalkanli 这个问题是关于XMLGregorianCalendar,这个问题似乎是关于GregorianCalendar(或者我不知道,但几乎没有XMLGregorianCalendar)。所以不是那个问题的重复,可能是其他问题。
  • 您是在编译时还是在运行时收到错误消息?您愿意引用错误消息 verbatim(将其粘贴到问题中)吗?提前谢谢。

标签: java date-conversion java.util.date date java.util.calendar


【解决方案1】:

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() ;

使用适当的类型

如果您尝试表示出生日期,通常只使用没有时间和区域的日期,然后在地图中使用LocalDateGregorianCalendarjava.util.DateZonedDateTime 类都代表一个时刻,时间线上的一个特定点。它们不应该仅用于日期。

java.sql.Date假装 是一个仅限日期的类,但是通过一个糟糕的设计决策,作为 java.util.Date 的子类,实际上确实带有时间和偏移量/区域.如上所述,该类已替换为LocalDate

普通日期对象

java.util.Datejava.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.Datejava.sql.Timestamp


关于java.time

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

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 的试验场。您可以在这里找到一些有用的类,例如IntervalYearWeekYearQuartermore

【讨论】:

    【解决方案2】:

    没有java类GregorianDate。除非这是您自己的课程,否则您没有提及。那么,以防万一公历日期只是一个普通的Date,因为今天世界上大多数人都使用公历?那么您的地图在您的HashMap<String, Object> 中包含哪些类的实例?如果它只是一个普通的Date,那么你的代码应该是:

    Date dateOfBirth = (Date)(customerSearch.get("DateOfBirth"));
    

    【讨论】:

      猜你喜欢
      • 2016-02-13
      • 2014-02-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-11-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多