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

如何将Java的ZonedDateTime存入Oracle的TIMESTAMPTZ类型字段?

问题原因
  1. 直接传入字符串存储时抛出not a valid month错误,是因为Oracle会话默认的NLS_TIMESTAMP_TZ_FORMAT参数和你传入的时间字符串格式不匹配,Oracle无法完成自动解析。
  2. 尝试构造TIMESTAMPTZ对象时抛出格式错误,是因为oracle.sql.TIMESTAMPTZ的字符串构造方法默认要求传入不带时区信息的时间字符串,会内部调用java.sql.Timestamp.valueOf做转换,而java.sql.Timestamp本身不支持携带时区偏移,你传入的带+02:00的字符串不符合它的格式要求,所以触发异常。
可行解决方案

方案一:直接使用ZonedDateTime存储(最推荐)

只要你使用的是ojdbc8及以上版本的Oracle驱动,原生支持Java 8+的java.time时间类型,可以直接映射到Oracle的TIMESTAMP WITH TIME ZONE字段,不需要依赖Oracle专有API:

import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;

// 解析时间字符串为ZonedDateTime对象
String timeStr = "2021-10-28 02:36:08.000000 +02:00";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSSSS XXX");
ZonedDateTime zonedDateTime = ZonedDateTime.parse(timeStr, formatter);

// 直接设置参数即可,驱动会自动完成类型映射
PreparedStatement ps = con.prepareStatement(query);
ps.setObject(1, zonedDateTime);

方案二:SQL层面指定格式解析

如果不想修改Java层面的时间处理逻辑,可以在SQL语句中用TO_TIMESTAMP_TZ函数指定格式,直接传入字符串参数:

  1. 编写SQL时指定时间格式:
INSERT INTO 你的表名 (时间字段名) VALUES (TO_TIMESTAMP_TZ(?, 'yyyy-mm-dd hh24:mi:ss.ff6 tzh:tzm'))
  1. Java代码直接传入字符串即可:
String d = "2021-10-28 02:36:08.000000 +02:00";
PreparedStatement ps = con.prepareStatement(query);
ps.setString(1, d);
注意事项
  • ojdbc版本需要匹配你使用的Oracle数据库版本,优先使用ojdbc8及以上版本,避免时间类型映射异常
  • 格式符要和时间字符串完全匹配:如果你的时间字符串是6位小数秒就写ff6,3位就写ff3,时区格式为±HH:MI就用tzh:tzm格式符
  • 不要使用java.sql.Timestamp做中转,该类不携带时区信息,转换过程中极易出现时区偏移错误

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 10:15:03