【问题标题】:FastDateFormat parser outputs incorrect timeFastDateFormat 解析器输出不正确的时间
【发布时间】:2017-12-15 15:49:30
【问题描述】:

我一直在摸不着头脑,试图理解为什么 FastDateFormat 解析器返回一个非常不正确的时间。我尝试转换的字符串时间戳是 GMT/UTC,我尝试将其插入 DB2 的时间戳列中。

代码如下:

String gmtTimestamp = "2017-03-12 02:38:30.417000000";
FastDateFormat fdf = FastDateFormat.getInstance("yyyy-MM-dd HH:mm:ss.SSSSSSSSS", TimeZone.getTimeZone("GMT"));
java.util.Date d = fdf.parse(gmtTimestamp);
Timestamp ts1 = new Timestamp(d.getTime());
System.out.println(ts1);

打印的时间是:“2017-03-16 17:28:30.0”,4 天和将近 15 个小时的休息时间。这里发生了什么?

【问题讨论】:

  • 您使用的是哪个版本的 apache.commons?
  • commons-lang3 版本 3.4
  • 不知道FastDateFormat的猜测:417000000被解释为毫秒,大约是4.8天。
  • Datetime parsing error 的可能重复项。我知道另一个问题是使用SimpleDateFormat,但这两个是等价的。

标签: java timestamp apache-commons


【解决方案1】:

TL;DR

    String gmtTimestamp = "2017-03-12 02:38:30.417000000";
    DateTimeFormatter dtf 
            = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss.SSSSSSSSS");
    Instant i1 = LocalDateTime.parse(gmtTimestamp, dtf)
            .atOffset(ZoneOffset.UTC)
            .toInstant();
    System.out.println(i1);

打印出来

2017-03-12T02:38:30.417Z

Instant.toString() 的隐式调用会生成 UTC 日期和时间(我们的目的与 GMT 相同),因此您可以从 GMT 字符串中识别日期和时间。

java.time

我建议您放弃 java.sql.Timestamp 课程。它已经过时了,今天我们在java.time,现代Java 日期和时间API 中提供了更好的功能。 Timestamp 的最初目的是在 SQL 数据库中存储和检索日期时间值。使用足够新的 JDBC 驱动程序 (JDBC 4.2),您可以并且希望利用 java.time 中的两个类来实现此目的:Instant 用于时间线上的一个点,LocalDateTime 用于没有时区的日期和时间.

如果您确实需要 Timestamp(例如对于旧版 API 或您现在不想升级的旧版 JDBC 驱动程序),请在提交之前将上面的 Instant 转换为 Timestamp到旧版 API 或数据库:

    Timestamp ts1 = Timestamp.from(i1);
    System.out.println(ts1);

在美国/芝加哥时区运行:

2017-03-11 20:38:30.417

Timestamp.toString() 抓取 JVM 的时区设置,并输出该时区的日期和时间(可能会造成混淆)。

你的代码 sn-p 发生了什么?

FastDateFormat 使用SimpleDateFormat 格式模式。在SimpleDateFormatFastDateFormat 中,大写S 表示毫秒。所以 417000000 被认为是毫秒(你想要 417 毫秒),它与 4 天 20 小时大致相同,它被添加到日期时间值中直到秒。我使用SimpleDateFormat 复制了您的结果,并将我的 JVM 设置为美国/芝加哥时区。 3 月距世界标准时间 -5 小时的其他时区将产生相同的结果。由于Timestamp 是在偏移量-5:00 打印的,因此输出的明显差异略小于4 天20 小时的实际差异,“仅”是4 天15 小时。

相比之下,尽管现代的DateTimeFormatter 大多使用相同的格式模式字母,但大写的S 表示秒的一小部分,这就是我们预期和期望得到30.417 秒的原因。

行情

所有模式都与 SimpleDateFormat 兼容(时区除外 和一些年份模式 - 见下文)。

(FastDateFormat documentation)

S Millisecond Number 978

(SimpleDateFormat documentation)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-25
    • 1970-01-01
    • 1970-01-01
    • 2020-09-05
    • 1970-01-01
    相关资源
    最近更新 更多