18

这是我将 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 like 但对于 with2017-11-21 18:11:14.05 失败。2017-11-21 18:11:14.057DateTimeParseException

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

4

6 回答 6

26

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

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);
于 2018-01-17T00:20:26.707 回答
21

Basil BourqueSleiman Jneidi的回答非常出色。我只是想指出,EMH333 的答案也有道理:对问题中的代码进行以下非常简单的修改可以解决您的问题。

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

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

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

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

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

于 2018-01-17T12:06:47.037 回答
14

tl;博士

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

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

ISO 8601

Sleiman Jneidi的答案特别聪明和高科技,但有一种更简单的方法。

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

您的输入几乎是合规的。只需将中间的空格替换为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


在此处输入图像描述

于 2018-01-17T04:57:03.847 回答
2

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

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 "";
  }
}
于 2018-01-17T01:26:48.703 回答
1

理想情况下,您也可以考虑 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");
于 2021-03-01T11:05:27.530 回答
0

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

于 2021-03-01T11:17:15.527 回答