ResultSet getDate() 返回不正确和正确的日期
Posted
技术标签:
【中文标题】ResultSet getDate() 返回不正确和正确的日期【英文标题】:ResultSet getDate() is returning incorrect and correct dates 【发布时间】:2019-12-03 21:00:22 【问题描述】:我正在从假期表中创建一个 LocalDate 列表。数据库表中的日期都是正确的,但是当我使用 ResultSet getDate() 方法并使用所有日期填充列表时,其中 4 个日期是错误的,6 个是正确的。我正在寻找任何帮助来弄清楚为什么会这样。
final LocalDate currentDay = LocalDate.now();
final List<LocalDate> holidays = getHolidays(currentDay);
//This method takes in a date and calculates the holidays that occur that year
public static List<LocalDate> getHolidays(final LocalDate date)
final List<LocalDate> holidayList = new ArrayList<LocalDate>();
try
final PreparedStatement holidaysByYearQuery = conn.prepareStatement(
"SELECT fulldate FROM holidays WHERE YEAR(fulldate) = ?");
holidaysByYearQuery.setObject(1, date.getYear());
final ResultSet holidaysByYearResult = holidaysByYearQuery.executeQuery();
while (holidaysByYearResult.next())
final Date holidate = (Date) holidaysByYearResult.getObject(1);
final LocalDate holiday = holidate.toLocalDate();
holidayList.add(holiday);
catch (final SQLException e)
LOGGER.log(Level.WARNING, "Could not query holiday table: " + e.getMessage());
return holidayList;
// This is the query used in Java:
com.mysql.cj.jdbc.PreparedStatement@1c27c773: SELECT fulldate FROM holidays WHERE YEAR(fulldate) = 2019
// Here is the list that is returned from the method
[2018-12-31, 2019-02-17, 2019-04-19, 2019-05-20, 2019-07-01, 2019-08-05, 2019-09-02, 2019-10-14, 2019-12-24, 2019-12-25]
这里是数据库表信息。这是非常基本的。
CREATE TABLE holidays(
province VARCHAR(255),
holiday VARCHAR(255),
fulldate DATETIME);
INSERT INTO holidays(province, holiday, fulldate) VALUES
('Ontario', 'New Years', '2019-01-01'),
('Ontario', 'Family Day', '2019-02-18'),
('Ontario', 'Good Friday', '2019-04-19'),
('Ontario', 'Victoria Day', '2019-05-20'),
('Ontario', 'Canada Day', '2019-07-01'),
('Ontario', 'Civic Holiday', '2019-08-05'),
('Ontario', 'Labour Day', '2019-09-02'),
('Ontario', 'Thanksgiving', '2019-10-14'),
('Ontario', 'Christmas Day', '2019-12-25'),
('Ontario', 'Boxing Day', '2019-12-26');
// This is the select result from the query above
+---------------------+
| fulldate |
+---------------------+
| 2019-01-01 00:00:00 |
+---------------------+
| 2019-02-18 00:00:00 |
+---------------------+
| 2019-04-19 00:00:00 |
+---------------------+
| 2019-05-20 00:00:00 |
+---------------------+
| 2019-07-01 00:00:00 |
+---------------------+
| 2019-08-05 00:00:00 |
+---------------------+
| 2019-09-02 00:00:00 |
+---------------------+
| 2019-10-14 00:00:00 |
+---------------------+
| 2019-12-25 00:00:00 |
+---------------------+
| 2019-12-26 00:00:00 |
+---------------------+
如您所见,列表两端的 2 个日期不正确。我假设 getDate() 方法发生了一些事情。任何人都可以对此有所了解吗?干杯。
【问题讨论】:
您的列的数据类型究竟是什么?您使用的是什么数据库系统? 如果您只存储日期,为什么要使用 DateTime 作为类型? ResultSet 有一个 getDate 方法。我的猜测是,这是关于时区和不同的夏令时变化 @BasilBourque DATETIME 和 Mysql(Innodb) @JoakimDanielson 这只是我现在拥有的模式。我之前使用过 DATE,它有完全相同的问题。 您对仅日期值使用了错误的类型。将您的列定义为DATE
。
【参考方案1】:
您为什么要将糟糕的遗留类Date
与现代LocalDate
混合在一起?你为什么要投射(Date)
?
SQL 标准 DATE
如果您的列属于类似于 SQL 标准 DATE
的类型,则将 LocalDate
与符合 JDBC 4.2 或更高版本的 JDBC 驱动程序一起使用。
LocalDate ld = myResultSet.getObject( … , LocalDate.class ) ;
SQL 标准 TIMESTAMP WITH TIME ZONE
如果您的列属于类似于 SQL 标准 TIMESTAMP WITH TIME ZONE
的类型,那么您必须考虑时区来确定日期。
OffsetDateTime odt = myResultSet.getObject( … , OffsetDateTime.class ) ;
ZoneId z = ZoneId.of( "Australia/Sydney" ) ;
ZonedDateTime zdt = odt.atZoneSameInstant( z ) ;
LocalDate ld = zdt.toLocalDate() ;
SQL 标准 TIMESTAMP WITHOUT TIME ZONE
如果您的列属于类似于 SQL 标准 TIMESTAMP WITHOUT TIME ZONE
的数据类型,例如 MySQL 类型 DATETIME
,请使用 Java 类型 LocalDateTime
。这种类型只有一个日期和时间,没有时区的上下文或与 UTC 的偏移量。所以这种类型确实不代表片刻。
LocalDateTime ldt = myResultSet.getObject( … , OffsetDateTime.class ) ;
LocalDate ld = ldt.toLocalDate() ;
【讨论】:
强制转换是旧的解决方案尝试,因为 resultSet.getDate() 不返回 LocalDate。使用 myResultSet.getObject( ... , LocalDate.class ) ;作品。 Date 和 LocalDate 的混合是导致这几个日期偏移的原因吗?我也很欣赏有关带和不带时区的信息。这似乎是一个更强大的解决方案。 @RWri - 对于东部标准时间 (EST) 生效的日期,Date
值不正确。 EDT 于 2019 年 3 月 10 日开始,将于 2019 年 11 月 3 日结束。除非指定了其他时区,否则 JDBC 的默认行为是将 java.sql.Date
与 JVM 的默认时区相关联。显然,元旦的日期/时间值被返回为2018-12-31 23:00:00 EST
,并且被截断为2018-12-31
。
@GordThompson 很有趣。你知道为什么它只在 4/10 的日期不正确吗?如果它是由时区引起的,我希望所有日期都会偏移。
@RWri re:“如果它是由时区引起的,我希望所有日期都会偏移。” - 不必要。例如,当您的 JVM 使用America/Toronto
时区(尊重 EST/EDT)而 MySQL 服务器使用固定的区域偏移量时,事情可能会变得混乱,例如,UTC-4
(不考虑标准/日光时间)。
Gord Thompson 的 cmets 是正确的,并说明了为什么永远不应该使用麻烦的遗留类,例如 java.sql.Date
、java.util.Date
和 Calendar
。以上是关于ResultSet getDate() 返回不正确和正确的日期的主要内容,如果未能解决你的问题,请参考以下文章
JDBC ResultSet:我需要一个 getDateTime,但只有 getDate 和 getTimeStamp
ResultSet 不为空,但 resultset.next() 返回 false