Bor*_*rka 15 java database timezone datetime jdbc
关于部分内容已经说了很多(并且写在SO上),但不是全面,完整的方式,所以我们可以有一个"终极,覆盖所有"的解决方案供所有人使用.
我有一个Oracle DB,我存储全局事件的日期+时间+时区,因此必须保留原始TZ,并根据请求传送到客户端.理想情况下,它可以很好地使用标准的ISO 8601"T"格式,可以使用"TIMESTAMP WITH TIME ZONE"列类型("TSTZ")很好地存储在Oracle中.
像"2013-01-02T03:04:05.060708 + 09:00"这样的东西
我需要做的就是从DB中检索上述值并将其发送到客户端而无需任何操作.
问题是Java缺乏ISO 8601(或任何其他日期+时间+ nano + tz数据类型)的支持,情况更糟,因为Oracle JDBC驱动程序(ojdbc6.jar)对TSTZ的支持更少(相对于Oracle DB本身得到了很好的支持).
具体来说,这是我不应该或不能做的:
那么,这是我留下的选项:
使用JDBC getString(),并对其进行字符串操作以修复并使ISO 8601兼容.这很容易做到,但如果Oracle更改内部硬编码的getString()格式,则存在死亡的危险.另外,通过查看getString()源代码,似乎使用getString()也会导致一些性能损失.
使用Oracle DB"toString"转换:"SELECT TO_CHAR(tstz ...)EVENT_TIME ...".这很好,但有两个主要的不利因素:
使用Oracle的TIMESTAMPTZ java类并从其内部(记录的)字节数组结构中手动提取相关值(即实现我自己的toString()方法,Oracle忘记在那里实现).如果Oracle改变内部结构(不太可能)并且需要相对复杂的功能来实现和维护,这是有风险的.
我希望有第四个,很棒的选择,但是从整个网络上看也是如此 - 我看不到任何东西.
想法?意见?
UPDATE
下面给出了很多想法,但看起来没有正确的方法来做到这一点.就个人而言,我认为使用方法#1是最短且最易读的方式(并保持良好的性能,而不会丢失亚毫秒或基于SQL时间的查询功能).
这是我最终决定使用的:
String iso = rs.getString(col).replaceFirst(" ", "T");
谢谢大家好的答案,
  B.
JDBC getObject() 或 getTIMESTAMPTZ() 都返回 Oracle 的 TIMESTAMPTZ 对象,这实际上是无用的,因为它没有任何转换为 Calendar(只有日期、时间和时间戳),因此我们再次丢失了 TZ 信息。
这将是我的建议,因为这是获取所需信息的唯一可靠方法。
如果您使用的是 Java SE 8 并且有 ojdbc8,那么您可以使用getObject(int, OffsetDateTime.class)。请注意,当您使用getObject(int, ZonedDateTime.class) 时,您可能会受到错误 25792016 的影响。
使用 Oracle 的 TIMESTAMPTZ java 类并从其内部(记录在案的)字节数组结构中手动提取相关值(即实现我自己的 toString() 方法,Oracle 忘记在那里实现)。如果 Oracle 改变内部结构(不太可能)并且需要相对复杂的功能来实现和维护,这是有风险的。
这就是我们最终采用的方法,直到 Oracle JDBC 驱动程序中提供无错误 JSR-310 支持。我们确定这是获取我们想要的信息的唯一可靠方式。
因为看起来没有神奇的方法可以正确地做到这一点,所以最简单和最短的方法是#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.
| 归档时间: | 
 | 
| 查看次数: | 16481 次 | 
| 最近记录: |