【问题标题】:java.sql.Timestamp to Date Conversion in Oracle SQLOracle SQL 中的 java.sql.Timestamp 到日期转换
【发布时间】:2018-10-29 15:47:58
【问题描述】:

我在 Oracle SQL 中遇到了这个奇怪的时间戳到日期转换问题。

SQL 语句如下:

String INSERT_SQL = String.format("INSERT INTO AUDIT_TASK (%s, %s, %s, %s) VALUES (AUDIT_TASK_SEQ.nextval,?,?,?)",ID,CLASS_NAME,TASK_STEP_TIMESTAMP,OPERATOR);

java.util.Calendar utcCalendarInstance = Calendar.getInstance(TimeZone .getTimeZone("UTC"));
java.util.Calendar cal = Calendar.getInstance();
final PreparedStatement stmt = con.prepareStatement(INSERT_SQL);
stmt.setString(1, audit.getClassName().getValue());
// Save the timestamp in UTC
stmt.setTimestamp(2,new Timestamp(cal.getTimeInMillis()), utcCalendarInstance);

当我执行此语句时,虽然大多数时候 creation_date 和 task_step_timestamp 日期是相同的,但有时我会生成带有一些虚假日期的 task_step_timestamp - 例如“25-APR-0000”或“00-Jan-0001”等等

  • ID |创建日期 | Task_step_timestamp
  • 1 |2018 年 4 月 27 日 17:58:53| 25-APR-0000 09:00:45
  • 2 |2018 年 4 月 27 日 18:06:25| 00-Jan-0001 09:18:25

Oracle DB中task_step_timestamp列的数据类型为'DATE'。

有人能指出时间戳到日期转换不一致的原因吗?

【问题讨论】:

标签: java sql oracle11g sql-date-functions sql-timestamp


【解决方案1】:

我不明白你为什么在这里使用String#format。只需使用提及显式列的常规插入:

String INSERT_SQL = "INSERT INTO AUDIT_TASK (ID, ERROR_MESSAGE, TASK_STEP_TIMESTAMP, OPERATOR) ";
INSERT_SQL += "VALUES (AUDIT_TASK_SEQ.nextval, ?, ?, ?)";
PreparedStatement stmt = con.prepareStatement(INSERT_SQL);

然后绑定你的值:

stmt.setString(1, audit.getErrorMessage() != null ? audit.getErrorMessage().getValue() : null);
stmt.setTimestamp(2, new Timestamp(cal.getTimeInMillis()), utcCalendarInstance);
stmt.setString(3, audit.getClassName().getValue());

请注意,占位符从左到右依次是错误消息、任务步骤时间戳和运算符。您的原始代码似乎无序地绑定参数。通过使用明确提及列的插入语句,您可以避免这个问题。

编辑:

对我来说,您为什么担心时间戳的时区也没有意义。只需获取自纪元以来的毫秒数,然后让数据库将其存储为 UTC:

Timestamp timestamp = new Timestamp(System.currentTimeMillis());
stmt.setTimestamp(2, timestamp);

【讨论】:

  • 是的,占位符的顺序不正确,因为我只是在这篇文章中包含了列名的子集。我的实际表格中有其他列,但我想跳过它们。我已在此处进行了更改,但仍需要找出错误的时间戳到日期转换。
  • 如果您能阐明时间戳背后的逻辑,也许我可以提出建议。顺便说一句,您应该在此处编辑您的问题。这可能会使其他人的工作无效。
  • 注意点。基本上,我需要记录事件创建/完成/出错的时间。因此,一旦此事件发生,我将其记录到数据库中,并将时间存储在 task_event_timestamp 中。 creation_Date 是 oracle DB 中的审计列。理想情况下,这两个表中的值应该匹配,并且它们在大多数情况下都会匹配,但有时它会在 task_timestamp 中给出不正确的日期。
  • 是不是因为Calendar有两种不同的实例类型?当我们向Timestamp 构造函数提供具有不同时区的Calender 实例时,cal.getTimeInMillis() 返回的Long 值是否转换不正确?
  • 我认为您不应该在这里使用日历。从纪元开始获取 ms 并插入到您的数据库中。让 Oracle 担心将其作为 UTC 进行管理。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-04-14
  • 2012-11-04
  • 2023-03-27
  • 2012-01-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多