java.time.format.DateTimeParseException: 在索引3处无法解析文本

52

我正在使用Java 8来解析日期并找到两个日期之间的差异。

这是我的代码片段:

String date1 ="01-JAN-2017";
String date2 = "02-FEB-2017";

DateTimeFormatter df = DateTimeFormatter .ofPattern("DD-MMM-YYYY", en);
LocalDate  d1 = LocalDate.parse(date1, df);
LocalDate  d2 = LocalDate.parse(date2, df);

Long datediff = ChronoUnit.DAYS.between(d1,d2);

当我运行时,出现错误:

java.time.format.DateTimeParseException: 在索引3处无法解析文本


java.time.format.DateTimeParseException:无法在第3个位置解析文本


请尝试使用"dd-MMM-yyyy"格式。 - NikNik
1
可能是如何使用jsr310 DateTimeFormatter解析不区分大小写的字符串?的重复问题。 - Sotirios Delimanolis
6个回答

64

首先,检查 javadoc。大写字母 D 表示年中的天数字段(而不是您想要的月中的天数),大写字母 Y 表示基于周的年份字段(而不是您想要的年份)。正确的模式是小写字母 dy

此外,您正在使用大写字母的月份名称(JANFEB),因此您的格式化程序必须是不区分大小写的(默认行为是仅接受像 JanFeb 这样的值)。并且这些月份名称是英文缩写,因此您还必须使用英文语言环境来确保它正确解析名称(使用 java.util.Locale 类)。

因此,您的格式化程序应该像这样创建:

DateTimeFormatter df = new DateTimeFormatterBuilder()
    // case insensitive to parse JAN and FEB
    .parseCaseInsensitive()
    // add pattern
    .appendPattern("dd-MMM-yyyy")
    // create formatter (use English Locale to parse month names)
    .toFormatter(Locale.ENGLISH);

这将使您的代码工作(datediff 将为 32)。


17
非常好的答案。涵盖了所有相关内容,而且言简意赅。 - Ole V.V.
5
添加语言环境对于解决我的错误信息(DateTimeParseException:无法解析索引为0的文本)非常关键,但这一点并不明显。感谢您的提示! - Flic

24
以下代码可以正常运行。问题在于您使用了“JAN”而不是“Jan”。 DateTimeFormatter无法识别它。同时,请将日期格式修改为“d-MMM-yyyy”。
  String date1 ="01-Jan-2017";
  String date2 = "02-Feb-2017";

  DateTimeFormatter df = DateTimeFormatter.ofPattern("d-MMM-yyyy");
  LocalDate  d1 = LocalDate.parse(date1, df);
  LocalDate  d2 = LocalDate.parse(date2, df);

  Long datediff = ChronoUnit.DAYS.between(d1,d2);  

来源: https://www.mkyong.com/java8/java-8-how-to-convert-string-to-localdate/


谢谢。它有效。我还有另一个问题。它会考虑夏令时吗? - Uma
2
@Uma,你不用担心夏令时的问题。即使夏令时在3月26日开始,从3月25日到3月26日还是完整的一天。使用“LocalDate”时,它会完全忽略实际只有23小时的事实。实际上,“LocalDate”忽略任何时区和因此忽略了任何夏令时问题。 - Ole V.V.

3
// DateTimeFormatterBuilder provides custom way to create a
    // formatter
    // It is Case Insensitive, Nov , nov and NOV will be treated same
    DateTimeFormatter f = new DateTimeFormatterBuilder().parseCaseInsensitive()
            .append(DateTimeFormatter.ofPattern("yyyy-MMM-dd")).toFormatter();
    try {
        LocalDate datetime = LocalDate.parse("2019-DeC-22", f);
        System.out.println(datetime); // 2019-12-22
    } catch (DateTimeParseException e) {
        // Exception handling message/mechanism/logging as per company standard
    }

2

也许有人正在寻找这个,它将与日期格式一起使用,例如3/24/202211/24/2022

DateTimeFormatter.ofPattern("M/dd/yyyy")

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("M/dd/yyyy");
       formatter = formatter.withLocale( Locale.US );  // Locale specifies human language for translating, and cultural norms for lowercase/uppercase and abbreviations and such. Example: Locale.US or Locale.CANADA_FRENCH
        LocalDate date = LocalDate.parse("3/24/2022", formatter);
        System.out.println(date);

1

尝试使用DateTimeFormatter dtf = DateTimeFormatter.ofPattern("dd-LLL-yyyy",Locale.ENGLISH);


我尝试过这个方法,但对我没有起作用。只有使用其他解决方案中提到的parseCaseInsensitive()才有效。 - eby

1
也许你可以使用这个通配符,
 String d2arr[] = {
            "2016-12-21",
            "1/17/2016",
            "1/3/2016",
            "11/23/2016",
            "OCT 20 2016",
            "Oct 22 2016",
            "Oct 23", // default year is 2016
            "OCT 24",  // default year is 2016
    };

    DateTimeFormatterBuilder builder = new DateTimeFormatterBuilder()
            .parseCaseInsensitive().parseLenient()
            .parseDefaulting(ChronoField.YEAR_OF_ERA, 2016L)
            .appendPattern("[yyyy-MM-dd]")
            .appendPattern("[M/dd/yyyy]")
            .appendPattern("[M/d/yyyy]")
            .appendPattern("[MM/dd/yyyy]")
            .appendPattern("[MMM dd yyyy]");

    DateTimeFormatter formatter2 = builder.toFormatter(Locale.ENGLISH);

https://coderanch.com/t/677142/java/DateTimeParseException-Text-parsed-unparsed-text 在此输入链接描述

这段文本涉及编程中的DateTimeParseException错误。它通常出现在将字符串转换为日期或时间时,因为解析程序无法解释输入的文本。该错误可以通过检查输入格式是否正确来避免。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接