You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过JDBC Oracle驱动获取Oracle数据库中无时区调整的DATE?

问题

执行以下代码读取Oracle 21c数据库的DATE字段时:

java.sql.Date date = resultSet.getDate("DATE_COLUMN");
// 假设数据库中存储的是'16/05/1993'

Oracle JDBC驱动会在后台自动做时区调整,最终java.sql.Date内部的UNIX时间戳可能和预期的16/05/1993 00:00:00 UTC不一致——比如原本的'16/05/1993'传到应用里可能变成'15/05/1993'。

现在需要获取DATE字段的原始形式,满足以下任一要求即可:

  1. 直接拿到日、月、年三个独立数值(比如日=16,月=5,年=1993)
  2. 得到的时间戳始终对应16/05/1993 00:00:00 UTC

有没有办法避免这种不必要的时区调整?


解决方案

一、直接提取年月日数值

1. SQL查询时拆分字段

直接在SQL里把DATE拆成年、月、日三个字段返回,完全规避时区转换:

SELECT
  EXTRACT(YEAR FROM DATE_COLUMN) AS DATE_YEAR,
  EXTRACT(MONTH FROM DATE_COLUMN) AS DATE_MONTH,
  EXTRACT(DAY FROM DATE_COLUMN) AS DATE_DAY
FROM YOUR_TABLE

Java代码里直接读取三个数值:

int year = resultSet.getInt("DATE_YEAR");
int month = resultSet.getInt("DATE_MONTH");
int day = resultSet.getInt("DATE_DAY");

2. 用Oracle原生DATE对象读取

如果不想改SQL,可通过Oracle JDBC提供的oracle.sql.DATE类直接获取原始日期信息:

import oracle.sql.DATE;

DATE oracleDate = (DATE) resultSet.getObject("DATE_COLUMN");
// 注意转换逻辑:getYear()返回的是相对于1900的差值,getMonth()返回0-11
int year = oracleDate.getYear() + 1900;
int month = oracleDate.getMonth() + 1;
int day = oracleDate.getDate(); // 直接返回1-31的日

这种方式不会触发任何时区调整,读取的就是数据库里存储的原始年月日。

二、获取对应UTC 0点的时间戳

1. 配置JDBC连接时区

在JDBC连接URL中指定时区为UTC,驱动会把数据库DATE当作UTC时间处理:

jdbc:oracle:thin:@//your-db-host:1521/your-db-service?oracle.jdbc.timezoneAsRegion=false&userTimezone=UTC

或者在加载JDBC驱动前设置系统属性:

System.setProperty("oracle.jdbc.timezoneAsRegion", "false");
System.setProperty("user.timezone", "UTC");

之后调用resultSet.getDate("DATE_COLUMN")得到的就是对应UTC 0点的时间戳。

2. SQL转换为UTC时间

在查询时把DATE字段转换成UTC时区的时间再返回:

SELECT CAST(SYS_EXTRACT_UTC(CAST(DATE_COLUMN AS TIMESTAMP)) AS DATE) AS UTC_DATE
FROM YOUR_TABLE

Java中读取UTC_DATE字段,得到的时间戳就对应目标UTC时间。


内容的提问来源于stack exchange,提问作者potato_programmer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 12:35:07