【问题标题】:Java 11 DateTimeParseException could not be parsed at index 20无法在索引 20 处解析 Java 11 DateTimeParseException
【发布时间】:2020-06-22 14:57:56
【问题描述】:

我正在尝试在 Java 11 中将字符串转换为 Date 对象。下面的代码给了我异常。尝试了不同的方法,到目前为止没有运气。任何帮助解决此错误消息?

String date = 'Mon Aug 02 16:33:10 EDT 2021'
OffsetDateTime odt = OffsetDateTime.now( ZoneId.systemDefault() ) ;
DateTimeFormatter formatter = new DateTimeFormatterBuilder().appendPattern("E MMM d H:m:s z yyyy").toFormatter().ofLocalizedDateTime(FormatStyle.LONG) .withZone(odt.getOffset());
LocalDateTime  localDateTime = LocalDateTime.parse(date, formatter);
System.out.println(localDateTime);
System.out.println(formatter.format(localDateTime));

错误

Exception in thread "main" java.time.format.DateTimeParseException: Text 'Mon Aug 02 16:33:10 EDT 2021' could not be parsed at index 20
    at java.base/java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:2046)
    at java.base/java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1948)
    at java.base/java.time.LocalDateTime.parse(LocalDateTime.java:492)
    at java_time_LocalDateTime$parse.call(Unknown Source)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:47)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:125)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:148)

【问题讨论】:

    标签: java java-time


    【解决方案1】:

    一个好的 IDE 会为您尝试编译的代码生成警告。例如 Eclipse 警告

    DateTimeFormatter 类型的静态方法 ofLocalizedDateTime(FormatStyle) 应该以静态方式访问

    Java 允许您通过引用表达式访问类的static 成员。尽管如此,大家还是一致认为您 should not,而忽略语言功能。

    针对您的具体情况,

    new DateTimeFormatterBuilder().appendPattern("E MMM d H:m:s z yyyy")
                .toFormatter()
                .ofLocalizedDateTime(FormatStyle.LONG)
                .withZone(odt.getOffset());
    

    静态DateTimeFormatter#ofLocalizedDate(FormatStyle)[...].toFormatter() 类型的引用表达式DateTimeFormatter 上调用。您似乎认为它是在实际的DateTimeFormatter 实例上调用的,但实际上它只是static 方法调用。 .toFormatter() 返回的实例被丢弃。您的代码本质上等同于

    new DateTimeFormatterBuilder().appendPattern("E MMM d H:m:s z yyyy")
                .toFormatter(); // thrown away
    
    DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.LONG)
                .withZone(odt.getOffset());
    

    换句话说,您的formatter 具有由ofLocalizedDateTime 选择的格式,而不是您尝试使用的"E MMM d H:m:s z yyyy"。据推测,对于您的默认 Locale,该格式无法解析您的日期字符串。

    尚不清楚您是否打算使用该方法。如果您知道具有适当格式的相应语言环境,则可以跳过您的自定义模式,只使用选定的模式

    Locale currentLocale = /* whatever is appropriate */;
    DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.LONG)
             .withLocale(currentLocale);
    

    然后解析你的日期字符串。

    否则,完全忽略该方法,只需使用您提供的模式和时区构建您的 DateTimeFormatter

    DateTimeFormatter formatter = new DateTimeFormatterBuilder().appendPattern("E MMM d H:m:s z yyyy")
                    .toFormatter()
                    .withZone(odt.getOffset());
    

    您可以从DateTimeFormatter class javadoc 中得知您的模式字符串

    E MMM d H:m:s z yyyy
    

    可以适当地解析你的日期字符串

    Mon Aug 02 16:33:10 EDT 2021
    

    无关,你确定LocalDateTime 是你需要的吗?您基本上会丢失原始字符串中的时区信息 (EDT)。此外,提供给withZoneZoneId 将被忽略以解析为LocalDateTime

    【讨论】:

      【解决方案2】:

      使用模式,EEE MMM dd HH:mm:ss z yyyy

      此外,由于您在日期时间字符串中使用时区而不是偏移量,因此您应该使用 ZonedDateTime 而不是 OffsetDateTime

      import java.time.LocalDateTime;
      import java.time.ZonedDateTime;
      import java.time.format.DateTimeFormatter;
      
      public class Main {
          public static void main(String[] args) {
              String strDate = "Mon Aug 02 16:33:10 EDT 2021";
              DateTimeFormatter formatter = DateTimeFormatter.ofPattern("EEE MMM dd HH:mm:ss z yyyy");
              ZonedDateTime zdt = ZonedDateTime.parse(strDate, formatter);
              System.out.println(zdt);
      
              LocalDateTime ldt = zdt.toLocalDateTime();
              System.out.println(ldt);
          }
      }
      

      输出:

      2021-08-02T16:33:10-04:00[America/New_York]
      2021-08-02T16:33:10
      

      注意 (Courtesy Basil Bourque):ZonedDateTime 转换为 LocalDateTime 几乎肯定没有意义。这种转换会丢弃有价值的信息,即时区,而不会增加任何价值。

      【讨论】:

      • 解释应该是冗长的,因为你完全忽略了根本原因。这里的问题是他们以非静态方式使用静态工厂方法ofLocalizedDateTime,完全跳过了他们一直在构建的DateTimeFormatterBuilder。它们的格式没有问题。
      【解决方案3】:

      在我的例子中,我正在解析的日期字符串是小写的 am/pm,像这样

      2021 年 5 月 12 日下午 3:31

      我必须先将 'pm' 转换为 'PM' 然后使用格式化程序 DateTimeFormatter.ofPattern("MMMM d yyyy 'at' h:mm a");

      【讨论】:

        猜你喜欢
        • 2020-06-10
        • 1970-01-01
        • 1970-01-01
        • 2019-02-15
        • 2021-01-15
        • 1970-01-01
        • 2020-02-16
        • 2021-09-10
        • 1970-01-01
        相关资源
        最近更新 更多