【问题标题】:JDBC timestamp escape format and SimpleDateFormat in JavaJava中的JDBC时间戳转义格式和SimpleDateFormat
【发布时间】:2012-07-29 06:01:37
【问题描述】:

我正在尝试使用SimpleDateFormat 模式来解析和格式化 JDBC 时间戳,特别是以下格式的日期yyyy-mm-dd hh:mm:ss.fffffffff,其中ffffffffff 表示纳秒。

很遗憾new SimpleDateFormat("yyyy-MM-dd-HH.mm.ss.SSS000000")不起作用,抛出如下异常:

java.text.ParseException: Format.parseObject(String) failed

SimpleDateFormat 是否有可能,或者我必须创建 java.text.DateFormat 的自定义子类来处理这种情况? 请注意,这不是关于如何在 Java 中解析yyyy-mm-dd hh:mm:ss.fffffffff 字符串的问题,我对声明性方法感兴趣,即不需要对输入字符串进行额外修改的 SimpleDateFormat 模式。

示例

我希望输入 2012-02-05 17:00:34.427000000 被解析为 java.util.Date,其中毫秒部分为 427

这是我迄今为止尝试过的格式列表,但由于各种原因,它们都失败了

  • new SimpleDateFormat("yyyy-MM-dd-HH.mm.ss.SSS000000") - java.text.ParseException: Format.parseObject(String) failed
  • new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSSSSSSSS", Locale.US)new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS", Locale.US) - 都被解析为 Fri Feb 10 15:37:14 而不是预期的 Sun Feb 05 17:00:34。 (427000000 的纳秒部分被视为毫秒,即使只指定了 SSS)

【问题讨论】:

  • “不起作用”非常模糊 - 会发生什么?
  • 抛出以下异常:java.text.ParseException: Format.parseObject(String) failed
  • 我基本上对以yyyy-mm-dd hh:mm:ss.fffffffff这种格式解析java.sql.Timestamp日期感兴趣,其中ffffffffff表示纳秒。
  • @ejboy:您希望所有信息都精确到纳秒吗?你没有在你的问题中提到根本。请阅读tinyurl.com/so-hints

标签: java timestamp simpledateformat


【解决方案1】:

我知道这是一个迟到的答案,但我一直在研究类似的问题,并且遇到了这个问题。

这里的问题是SimpleDateFormat 期待java.util.Date,它没有纳秒字段。所以,它不处理这种情况。 java.sql.Timestamp 文档说它是 java.util.Date 和纳秒字段的组合。 的日期/时间值存储在对象的日期部分中。这意味着可以忽略剩余的毫秒数以支持纳秒字段。在我看来,这是一个糟糕的设计,因为java.sql.Timestampjava.util.Date 的直接子类。

无论如何,要回答这个问题,我认为不可能在不附加到SimpleDateFormat 生成的字符串的情况下以纳秒打印时间戳。

这是一种方法:

    Timestamp timestamp = new Timestamp(System.currentTimeMillis());
    SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd-HH.mm.ss.");
    format.setTimeZone(TimeZone.getDefault()); // Set the TimeZone to whatever you are expecting.

    System.out.println(format.format(timestamp) + String.format("%09d", timestamp.getNanos());   

编辑:

为纳秒字符串值添加了填充。

【讨论】:

  • 好答案。而且,是的,java.sql.Timestamp 是一个 hack。所有旧的日期时间类(java.util.Date、.Calendar、SimpleDateFormat)都是一团糟。
  • The java.sql.Timestamp doc 实际上注意到了 hacky 的性质:Due to the differences between the Timestamp class and the java.util.Date class mentioned above, it is recommended that code not view Timestamp values generically as an instance of java.util.Date. The inheritance relationship between Timestamp and java.util.Date really denotes implementation inheritance, and not type inheritance.
  • 哦,我没看到。在这种情况下,创建一个不从 java.util.Date 继承的 SQL 时间戳类会更有意义。如有必要,它可以在内部包装 java.util.Date。
  • 我们现在确实有你建议的这样一个类:Instant,Java 8 中内置的java.time package 的一部分。Instant 具有nanoseconds 分辨率,因此不会丢失分数秒。 java.sql.Timestamp 类已扩展为现在提供toInstantfrom(即时)方法。因此您可以使用现有的 JDBC 驱动程序。
  • @Basil_Bourque 这是一个非常需要的改进;感谢您指出。但是,您可以将现有 JDBC 驱动程序与此功能一起使用的程度取决于它们支持的 JDBC 版本以及您在编写 JDBC 应用程序时要多小心。例如,您可以使用支持 JDBC 4.1 的驱动程序,但由于您将使用 Java 8 进行编译以获得该功能,因此您必须小心不要调用 4.2 中引入的任何方法。
【解决方案2】:

编辑:现在您已经给了我们一个数据样本,它相当简单:

"yyyy-MM-dd HH:mm:ss.SSS"

这肯定会解析您给出的值。您可能还想明确指定Locale.US,这样它就不会尝试使用不同的分隔符...

编辑:超过毫秒的尾随数据会导致问题。但是,数据的早期部分是固定长度的(我相信是 23 个字符),因此您应该可以编写:

Date date = format.parse(text.substring(0, 23));

【讨论】:

  • 这不起作用。问题是 SSS 会消耗包括零在内的整个部分,而不仅仅是前 3 位。
  • @ejboy:好吧,如果你能给我们一些测试数据并解释你想要发生什么以及会发生什么,那么帮助你会容易得多。跨度>
  • 您的答案没有给出正确的结果。检查 new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS", Locale.US) 它返回 Feb 10 15:37:14 供我输入。
  • @ejboy:嗯。看着。看起来是额外的 0 导致了问题。
  • @magiconair:被问到时确实如此。 OP只是在后面添加了“不修改输入字符串”的要求。
【解决方案3】:

RFC3339 的日期格式为:

yyyy-MM-dd'T'HH:mm:ss.SSS'Z'

除非您有来自资源提供者的不同日期格式。'

如果你有小数秒:

yyyy-MM-dd'T'HH:mm:ss.SSSSSS'Z'

编辑:根据你的例子,我解析你的字符串的格式是:

DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSSSSSSSS");

【讨论】:

  • 不幸的是,这些模式不包括我的情况。我已经澄清了这个问题。请使用示例作为参考。
  • 提议的模式不会导致异常,但是日期解析不正确。输入字符串2012-02-05 17:00:34.427000000 将给出2012-02-10 15:37:14.000 作为结果
  • 这是.427 之后的尾随零。我猜你必须在DateFormat 中解析日期文本之前对其进行子串化。
猜你喜欢
  • 1970-01-01
  • 2015-11-19
  • 2015-01-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-04-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多