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

How to parse date-time with two or three milliseconds digits in java?

这是我将字符串解析为 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();
    }

但这仅适用于输入字符串,例如 2017-11-21 18:11:14.05 但失败 2017-11-21 18:11:14.057 DateTimeParseException.

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

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

DateTimeFormatter 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);

使用 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 "";
  }
}

tl;博士

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

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

ISO 8601

特别聪明和高科技,但还有更简单的方法。

调整您的输入字符串以符合 ISO 8601 格式,该格式在 java.time 类 中默认使用。所以根本不需要指定格式模式。对于小数秒,默认格式化程序可以处理零(整秒)到九(纳秒)之间的任意小数位数。

您的输入几乎符合要求。把中间的SPACE换成T就可以了。

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

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


and are excellent. I just wanted to point out that 的回答也有一定道理:对问题中的代码进行以下非常简单的修改即可解决您的问题。

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

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

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

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

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

理想情况下,您也应该考虑具有 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");

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