当前位置: 首页 > 面试题库 >

Oracle / JDBC:以ISO 8601格式检索TIMESTAMP WITH TIME ZONE值

易波涛
2023-03-14
问题内容

关于该主题的某些部分已经说了很多(并用SO写过),但没有以一种全面,完整的方式进行,因此我们可以有一个“最终的,涵盖所有方面的”解决方案供所有人使用。

我有一个Oracle数据库,用于存储全局事件的日期+时间+时区,因此必须保留原始TZ,并根据请求将其交付给客户端。理想情况下,通过使用标准ISO 8601“
T”格式可以很好地工作,该格式可以使用“ TIMESTAMP WITH TIME ZONE”列类型(“ TSTZ”)很好地存储在Oracle中。

类似于 “ 2013-01-02T03:04:05.060708 + 09:00”

我需要做的就是从数据库中检索以上值并将其发送给客户端,而无需进行任何操作。

问题在于Java缺乏对ISO 8601(或任何其他date + time + nano + tz数据类型)的支持,而且情况甚至更糟,因为Oracle
JDBC驱动程序(ojdbc6.jar)对TSTZ的支持甚至更少(与Oracle DB本身得到了很好的支持)。

具体来说,这是我不应该或不能做的事情:

  • 从TSTZ到Java日期,时间,时间戳的任何映射(例如,通过JDBC getTimestamp()调用)都将不起作用,因为我丢失了TZ。
  • Oracle JDBC驱动程序不提供任何将TSTZ映射到Java Calendar对象的方法(这可能是一个解决方案,但不存在)
  • JDBC getString()可以工作,但是Oracle JDBC驱动程序返回格式为
    ‘2013-01-02 03:04:05.060708 +9:00’的字符串,该格式与ISO 8601不兼容(无“
    T”,TZ中没有尾随0等)。此外,这种格式在Oracle
    JDBC驱动程序实现中采用硬编码(!),它也忽略JVM语言环境设置和Oracle会话格式设置(即,它忽略NLS_TIMESTAMP_TZ_FORMAT会话变量)。

  • JDBC的getObject()或getTIMESTAMPTZ()都返回Oracle的TIMESTAMPTZ对象,该对象实际上是无用的,因为它没有对Calendar的任何转换(仅日期,时间和时间戳),因此,我们再次丢失了TZ信息。

所以,这是我剩下的选项:

  1. 使用JDBC getString(),并对其进行字符串处理以修正并使其与ISO 8601兼容。这很容易做到,但是如果Oracle更改内部硬编码的getString()格式,就有死亡危险。另外,通过查看getString()源代码,似乎使用getString()也会导致性能下降。

  2. 使用Oracle DB“ toString”转换:“ SELECT TO_CHAR(tstz …)EVENT_TIME …”。效果很好,但有两个主要缺点:

    • 现在,每个SELECT都必须包含TO_CHAR调用,这让人难以记住和编写
    • 现在,每个SELECT都必须添加EVENT_TIME列“ alias”(例如,需要将结果自动序列化到Json)
  3. 使用Oracle的TIMESTAMPTZ Java类,并从其内部(已记录的)字节数组结构中手动提取相关值(即,实现我自己忘了在Oracle中实现的我自己的toString()方法)。如果Oracle(不太可能)更改内部结构并要求实施和维护相对复杂的功能,则存在风险。

  4. 我希望有第4个绝佳的选择,但是从整个Web和SO的角度来看-我看不到任何东西。

有想法吗?意见?

更新

下面给出了很多想法,但是似乎没有合适的方法来做到这一点。就我个人而言,我认为使用 方法1 是最短,最易读的方式(并保持良好的性能,
而又不会损失毫秒级或基于SQL时间的查询功能 )。

这是我最终决定使用的:

String iso = rs.getString(col).replaceFirst(" ", "T");

谢谢大家的良好回答,
B。


问题答案:

由于似乎没有神奇的方法可以做到这一点,因此最简单,最短的方法就是#1。具体来说,这就是所需的所有代码:

// convert Oracle's hard-coded: '2013-01-02 03:04:05.060708 +9:00'
// to properly formatted ISO 8601: '2013-01-02T03:04:05.060708 +9:00'
String iso = rs.getString(col).replaceFirst(" ", "T");

似乎只需添加
T”就足够了,尽管一个完美主义者可能会放更多的化妆品(当然可以优化正则表达式),例如:rs.getString(col).replaceFirst(“”,“
T”)。replaceAll(“ “,”“).replaceFirst(” \ +([0-9])\:“,” + 0 $ 1:“);

B.



 类似资料:
  • 问题内容: 我使用数据类型将日期和时间存储在数据库中。将日期另存为 我可以从数据库中检索格式的时间,但我想以格式检索它。 我怎样才能做到这一点? 问题答案: 检查DATE_FORMAT函数。

  • 问题内容: 我正在使用bootstrap-datetimepicker和ISO8601 datetime格式,如其选项部分所述 在我的控制器中 它以(console.log)将数据发送到后端 并保存为数据库 在我的模板中 我在HTML上看到的输出为 但是根据Angular doc,它应该用于格式 我想念的是什么? 问题答案: 现在,我已经创建了一个过滤器 作为依赖项添加为 并用作 并将日期显示为

  • 我需要调用一个Oracle过程,其中一个IN参数与VARCHAR2和OUT参数作为BOOLEAN数据类型。 下面是我使用SimpleJDBCall的代码 异常: CallableStatementCallback;SQL未分类的SQLExctive[{callPACKAGE_NAME.PROC_NAME(?, ?)}]; SQL状态[99999];错误代码[17004];无效列类型: 16;嵌套异

  • 问题内容: 我在该网站和Google上进行了查看,但似乎找不到针对我要尝试的解决方案的好方法。 基本上,我有一个客户端服务器应用程序(C#),在其中向服务器发送一条SQL select语句(连接到SQL Server 2008),并希望以CSV方式将结果返回给客户端。 到目前为止,我有以下内容: }` 不幸的是,我真的是C#与SQL连接的新手。我需要有关如何将结果简单地以csv格式放入字符串的任何

  • 我有一个要求,通知客户,他们的证书将在一些日子过期,所以在那之前续订工作TLS加密工作预期。 如何检索PEM格式证书的到期时间?

  • 本文向大家介绍使用JDBC连接ORACLE的三种URL格式,包括了使用JDBC连接ORACLE的三种URL格式的使用技巧和注意事项,需要的朋友参考一下 使用jdbc连接oracle时url有三种格式 格式一: Oracle JDBC Thin using an SID:  这种格式是最简单也是用得最多的 你的oracle的sid可以通过一下指令获得: 格式二:  Oracle JDBC Thin