我有一个带有 Date 列的Oracle表。
+--------+-----------------------+
| ID | CURR_DATE |
+--------+-----------------------+
| 1 |2003-04-06 02:59:59 |
+--------+-----------------------+
当我做
select * from tablename
在数据库控制台中,我获得了CURR_DATE的正确列值。
但是当我使用JDBC在Java程序中执行相同操作时,由于夏令时,时间向前移动了一个小时。这是一个解释它的链接。 https://www.timeanddate.com/time/change/usa/new-york?year=2003。
所以我收到的值是2003-04-06 03:59:59 ,而不是2003-04-06 02:59:59 。
发生这种情况是因为DB和JVM在PST中并且PST遵循DST(如果我错了,请纠正我)
这是我的代码
String query="select * from tablename";
PreparedStatement psmt = con.prepareStatement(query);
ResultSet results=psmt.executeQuery();
while(results.next()) {
System.out.println(results.getString(2));
}
可以做些什么,以便results.getString()
向我返回数据库中相同的值(无需任何调整)。
我希望它返回原始值2003-04-06 02:59:59 ,而不是调整后的值2003-04-06 03:59:59 >。
答案 0 :(得分:2)
As @gord-thompson explained you should use an up to date ojdbc8 or ojdbc10, ideally 19.3 or 18.3, you can use these even if your database is 11.2g https://www.oracle.com/technetwork/database/enterprise-edition/jdbc-faq-090281.html#01_02
results.getObject(2, LocalDateTime.class)
Explanation
The issue is really with the implementation of the java.sql.Timestamp
class. It represents the milliseconds since 1970-01-01 00:00:00 GMT and 2003-04-06 02:59:59 in JVM time zone, 2003-04-06 02:59:59 does not exist in JVM time zone so the parser is off by the DST change.
LocalDateTime
is not bound to any time zone and just year-month-day-hour-minute-second-nano and therefore has no issues representing 2003-04-06 02:59:59 whatever the JVM time zone.
答案 1 :(得分:1)
java.time.LocalDateTime ldt = myResultSet.getObject( … , LocalDateTime.class ) ;
您将日期时间值存储在日期时间列中,因此请在Java中使用日期时间类型。当前,您正在使用字符串。
Oracle DATE
类型仅保留日期和日期,没有任何时区或UTC偏移量的概念。因此,DATE
列不能用于表示时刻。标准SQL中的等效项是TIMESTAMP WITHOUT TIME ZONE
。
例如,如果某行在今年1月23日中午在该列中存储了一个值,则我们知道如何知道这是东京中午,加尔各答中午,巴黎中午还是中午。蒙特利尔。这些不同的正午都发生在不同的时刻,相隔数小时。
Java中与Oracle DATE
列匹配的适当类型为LocalDateTime
。此类也缺少任何时区或从UTC偏移的概念。所以它不能用来代表一个时刻。但是,当您只有日期和时间而没有区域/偏移量时,这是适合您的课程。
JDBC 4.2和更高版本要求支持直接与数据库交换 java.time 对象。
LocalDateTime ldt = myResultSet.getObject( … , LocalDateTime.class ) ;
写数据。
myPreparedStatemen.setObject( … , ldt ) ;
通过用没有任何区域/偏移的类型的数据库列交换没有任何区域/偏移的Java对象,您将对区域/偏移没有任何疑问。但是请注意这种日期时间值的局限性: