【问题标题】:java date format with 6 digit micro/milli second6位微/毫秒的java日期格式
【发布时间】:2015-01-10 01:08:33
【问题描述】:

从 Postgres 数据库中,我得到一个 6 位数的微秒(实际上是一个),例如2014-11-10 04:05:06.999999

现在,当我应用“yyyy-MM-dd HH:mm:ss.SSS”的日期格式时,它会将 999999 转换为相应的秒/分钟,从而导致日期不正确。见下面的代码sn-p

String dt = "2014-11-10 04:05:06.999999";           
        String timeseriesFormat = "yyyy-MM-dd HH:mm:ss.SSS";            
        SimpleDateFormat dateFormat = new SimpleDateFormat(timeseriesFormat);
        Date date = dateFormat.parse(dt);
        System.out.println(dateFormat.format(date));

结果于 2014-11-10 04:21:45.999

我想截断最后 3 位数字并保留 2014-11-10 04:05:06.999 的日期。 如何截断它?我不想使用任何框架,如 joda 等。

【问题讨论】:

  • 出现的微秒是 0 填充的吗? 2014-11-10 04:05:06.152014-11-10 04:05:06.000015 有所不同。

标签: java date format


【解决方案1】:

java.time

使用 Java 8 及更高版本中内置的 java.time 类。永远不要使用糟糕的遗留日期时间类,例如 DateCalendarSimpleDateFormatGregorianCalendarTimestamp

从 JDBC 4.2 起,我们可以直接与数据库交换 java.time 对象。

String input = "2014-11-10 04:05:06.999999".replace( " " , "T" ) ; // Convert from SQL style to ISO 8601 standard format where `T` separates the year-month-day portion from hour-minute-second portion.
LocalDateTime ldt = LocalDateTime.parse( input ) ;

没有一刻

请注意,LocalDateTime不是瞬间,不是时间轴上的一个点。您的输入缺少时区或与 UTC 偏移的上下文。因此,我们不知道您的意思是日本东京 10 日凌晨 4 点、法国图卢兹凌晨 4 点,还是美国俄亥俄州托莱多凌晨 4 点——三个非常不同的时刻,在时间轴上相隔几个小时。

因此,您将把 LocalDateTime 对象的值存储在类型为 TIMESTAMP WITHOUT TIME ZONE 的 Postgres 数据库列中。

片刻

如果您的意图是表示一个时刻,时间轴上的一个特定点,那么您最清楚地知道预期的时区。

假设您知道凌晨 4 点是在日本东京时区。将ZoneId 应用于LocalDateTime 以获取ZonedDateTime 对象。

ZoneId z = ZoneId.of( "Asia/Tokyo" ) ;
ZonedDateTime zdt = ldt.atZone( z ) ;

不幸的是,JDBC 4.2 规范不要求支持两种最常用的类型,InstantZonedDateTime。无论如何,我们都可以轻松转换为OffsetDateTime,这是JDBC规范需要支持的。

OffsetDateTime odt = zdt.toOffsetDateTime() ;

这样一个值,时间线上的一个特定点,应该写入TIMESTAMP WITH TIME ZONE类型的数据库列。

写入数据库。

myPreparedStatement.setObject( … , odt ) ;

和检索。

myResultSet.getObject( … , OffsetDateTime.class ) ;

java.sql.Timestamp

如果您无法迁移到 Java 8,那么您应该使用 JDBC 驱动程序来获取 java.sql.Timestamp 对象。该课程是一个黑客,但它有效。它是一个 java.util.Date 但跟踪小数秒到纳秒而不是毫秒的分辨率。所以它将保留 Postgres 使用的微秒。

您可以将它用作 java.util.Date,但在其他情况下,您将失去额外的分辨率。

但是,您现在真的坚持使用 Java 6、7 还是 2020 年初的版本?最好迁移到 Java 8 或 Java 11,这两个 LTS 版本。



关于java.time

java.time 框架内置于 Java 8 及更高版本中。这些类取代了麻烦的旧 legacy 日期时间类,例如 java.util.DateCalendarSimpleDateFormat

要了解更多信息,请参阅Oracle Tutorial。并在 Stack Overflow 上搜索许多示例和解释。规格为JSR 310

Joda-Time 项目现在位于maintenance mode,建议迁移到java.time 类。

您可以直接与您的数据库交换 java.time 对象。使用符合JDBC 4.2 或更高版本的JDBC driver。不需要字符串,不需要java.sql.* 类。 Hibernate 5 & JPA 2.2 支持 java.time

从哪里获取 java.time 类?

【讨论】:

    【解决方案2】:

    复制到这个Custom date format cannot be parsed.

    结论是SimpleDateFormat不支持微秒,你需要自己的解析器

    试试这个:

    System.out.println(
    new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.").format(microseconds/1000)
    +String.format("%06d", microseconds%1000000));
    

    【讨论】:

    • 好的...有人可以分享自定义解析器吗?
    • Java 8 及更高版本现在在 java.time 框架中内置了这样的解析器。见my Answer
    【解决方案3】:

    试试dt.substring(0, dt.length() - 3)

    【讨论】:

    • 这只是一个例子。但是从数据库中我得到一个日期对象而不是字符串。如果我转换为字符串,则上述问题已经出现,因此应用修复为时已晚。
    • @user1712512 此评论与您的​​问题相矛盾,即您有一个字符串。
    猜你喜欢
    • 2015-12-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-12
    • 1970-01-01
    • 2012-07-11
    • 2019-04-08
    • 1970-01-01
    相关资源
    最近更新 更多