从数据库加载后,Java Date toString以不同的格式

如何在Java持久化之前和之后以可靠的方式比较日期? 我面临的问题是:当我创建java.util.Date的新实例时,它的toString()方法返回一个值,包括星期几和时区:

Fri Feb 03 10:15:31 CET 2017 

当我在数据库表中保留此日期(EDIT:Date对象)并将其加载回实体时,toString方法返回不同的格式,具体取决于数据库类型:

 In case of MySQL date: 2017-02-03 In case of MySQL datetime: 2017-02-03 10:24:34.0 

我并不总是有权访问格式化程序,因为toString方法可能会被我的应用程序中的另一个toString方法隐式调用。

这些问题对我而言:

  1. 使用toString时,Date对象如何知道要选择哪种格式?
  2. 如何控制新的Date对象,它应该首先代表一个日期(即没有时间分数的一天)?
  3. 在对象从数据库加载之前和之后的unit testing中比较持久对象的日期的最佳做法是什么?

使用对象,而不是字符串

不要使用字符串将数据传入/传出数据库。 使用对象。 这就是JDBC的目的,即从数据库的数据类型转换为Java的数据类型(类)。

使用java.time,而不是遗留类

不要使用旧的日期时间类,例如java.util.Date因为它们非常麻烦,令人困惑和有缺陷。 现在遗留下来,取而代之的是java.time类。

使用toString时,Date对象如何知道要选择哪种格式?

toString使用的格式是硬编码的,未选中。 您总是从该方法获得相同的格式。 而且格式选择较差,而现代图书馆和协议使用标准的ISO 8601格式。

java.time.Date许多糟糕的设计选择包括toString方法的行为,该方法将JVM的当前默认时区应用于实际为UTC的值。 这会产生实际上不存在的时区的错觉。

最好避免这些字符串。 在Java和数据库之间传递和获取对象而不是字符串。 调用PreparedStatement::setObjectResultSet::getObject方法以使用LocalDateInstant和其他此类java.time对象。

 LocalDate ld = myResultSet.getObject( … ); 

如果您的JDBC驱动程序尚未符合JDBC 4.2 ,并且无法直接处理java.time对象,请回过头来简要地使用java.sql类型。 通过调用添加到旧类的新方法,立即将这些java.sql对象转换为java.time对象。

 java.sql.Date myJavaSqlDate = myResultSet.getDate( … ); java.time.LocalDate ld = myJavaSqlDate.toLocalDate(); 

如何控制新的Date对象,它应该首先代表一个日期(即没有时间分数的一天)?

使用LocalDate类获取没有时间且没有时区的仅限日期的值。 这映射到SQL标准DATE类型的等效项。 您应该使用仅日期类型来定义数据库中的列。

在对象从数据库加载之前和之后的unit testing中比较持久对象的日期的最佳做法是什么?

LocalDate类提供比较方法,例如compareToisAfterisBeforeisEqual 。 其他课程类似。

在Stack Exchange上已经多次覆盖这一点。 请搜索类名,例如LocalDateInstantOffsetDateTimeZonedDateTimeZoneIdjava.sql.Timestamp