如何用java中的两个或三个毫秒数字解析日期时间?

时间:2018-01-17 00:07:37

标签: java datetime-format java-time datetime-parsing dateformatter

这是我将String解析为LocalDateTime的方法。

    public static String formatDate(final String date) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SS");
        LocalDateTime formatDateTime = LocalDateTime.parse(date, formatter);
        return formatDateTime.atZone(ZoneId.of("UTC")).toOffsetDateTime().toString();
    }

但这仅适用于输入String之类的 2017-11-21 18:11:14.05 但是2017-11-21 18:11:14.057失败了 与DateTimeParseException

如何定义适用于.SS.SSS的格式化程序?

6 个答案:

答案 0 :(得分:12)

您需要构建具有指定分数的格式化程序

DateTimeFormatterformatter formatter = new DateTimeFormatterBuilder()
  .appendPattern("yyyy-MM-dd HH:mm:ss")
  .appendFraction(ChronoField.MILLI_OF_SECOND, 2, 3, true) // min 2 max 3
  .toFormatter();

LocalDateTime formatDateTime = LocalDateTime.parse(date, formatter);

答案 1 :(得分:3)

TL;博士

根本不需要定义格式化程序。

LocalDateTime.parse(
    "2017-11-21 18:11:14.05".replace( " " , "T" )
)

ISO 8601

Answer by Sleiman Jneidi特别聪明且高科技,但有一种更简单的方法。

调整输入字符串以符合ISO 8601格式,即java.time类中默认使用的格式。因此,根本不需要指定格式化模式。默认格式化程序可以处理小数秒(零秒(整秒)和九(纳秒))之间的任意数量的十进制数字。

您的输入几乎符合要求。只需用T替换中间的SPACE即可。

String input = "2017-11-21 18:11:14.05".replace( " " , "T" );
LocalDateTime ldt = LocalDateTime.parse( input );
  

ldt.toString():2017-11-21T18:11:14.050

答案 2 :(得分:3)

Basil BourqueSleiman Jneidi的答案非常好。我只想指出the answer by EMH333也有一点意义:以下对问题中代码的非常简单的修改可以解决您的问题。

    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.[SSS][SS]");

格式模式字符串中的方括号包含可选部分,因此在小数秒内接受3或2个小数。

  • 与Basil Bourque的答案相比,潜在的优势:提供更好的输入验证,如果只有1或者秒上有四位小数,则会反对(这是否有利于完全取决于您的情况)。
  • 优于Sleiman Jneidi的回答:你不需要建造者。

可能的缺点:它根本不接受小数(只要有小数点)。

正如我所说,其他解决方案也非常好。你喜欢哪一个主要是品味问题。

答案 3 :(得分:1)

使用Java 8,您可以使用DateTimeFormatterBuilder和模式。有关更多信息,请参阅this answer

public static String formatDate(final String date) {

  DateTimeFormatterBuilder dateTimeFormatterBuilder = new DateTimeFormatterBuilder()
        .append(DateTimeFormatter.ofPattern("" + "[yyyy-MM-dd HH:mm:ss.SSS]" 
         + "[yyyy-MM-dd HH:mm:ss.SS]"));

  DateTimeFormatter formatter = dateTimeFormatterBuilder.toFormatter();

  try {
    LocalDateTime formatDateTime = LocalDateTime.parse(date, formatter);
    return formatDateTime.atZone(ZoneId.of("UTC")).toOffsetDateTime().toString();
  } catch (DateTimeParseException e) {
    return "";
  }
}

答案 4 :(得分:0)

理想情况下,您还要考虑 0 纳秒的时间。如果时间恰好恰好落在 2021-02-28T12:00:15.000Z 上,它实际上可能会被序列化为 2021-02-28T12:00:15Z(至少,对于像 java.time.OffsetDateTime 这样的东西)。因此,使用以下内容更合适:

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss[.SSS][.SS][.S]");

...如果你需要时区,就像我一样,那么它看起来像这样:

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss[.SSS][.SS][.S]z");

答案 5 :(得分:0)

我曾经参与过一个项目,其中输入可以是任何格式的字符串,如果它是有效格式,我们应该在事先不知道格式的情况下解析它。所以,我想出了一个想法,我们把所有支持的格式列表作为一个属性,然后当 String 进来时,我们尝试用列表中的格式一一解析它,直到我们成功或用完格式(在在这种情况下,我们将字符串变暗以使其不是有效的日期格式)。如果我们解析某些字符串失败并发现它是一个有效字符串,我们可以在不需要更改代码的情况下向我们的属性添加新格式,因此我们可以立即提供对任何新格式的支持,并拥有不同的支持格式集针对不同的客户。另一个问题是美国与欧洲格式 - 所以我们将美国格式和欧洲格式按顺序排列。因此客户可以说如果 String 适合两者,则选择列表中的第一个。因此,美国/欧盟格式支持列表中的格式顺序也是一个问题。这是解释思想和实现的文章的链接(包括格式列表的示例)Java 8 java.time package: parsing any string to date