Java:无法从 TemporalAccessor 获取 LocalDate

问题描述 投票:0回答:5

我正在尝试将

String
日期的格式从
EEEE MMMM d
更改为
MM/d/yyyy
,首先将其转换为
LocalDate
,然后在解析之前将不同模式的格式化程序应用于
LocalDate
再次进入
String

这是我的代码:

private String convertDate(String stringDate) 
{
    //from EEEE MMMM d -> MM/dd/yyyy

    DateTimeFormatter formatter = new DateTimeFormatterBuilder()
            .parseCaseInsensitive()
            .append(DateTimeFormatter.ofPattern("EEEE MMMM d"))
            .toFormatter();

    LocalDate parsedDate = LocalDate.parse(stringDate, formatter);
    DateTimeFormatter formatter2 = DateTimeFormatter.ofPattern("MM/d/yyyy");

    String formattedStringDate = parsedDate.format(formatter2);

    return formattedStringDate;
}

但是,我收到了一条我不太理解的异常消息:

Exception in thread "main" java.time.format.DateTimeParseException: Text 'TUESDAY JULY 25' could not be parsed: Unable to obtain LocalDate from TemporalAccessor: {DayOfWeek=2, MonthOfYear=7, DayOfMonth=25},ISO of type java.time.format.Parsed
    at java.time.format.DateTimeFormatter.createError(DateTimeFormatter.java:1920)
java java-time date-parsing localdate
5个回答
14
投票

正如其他答案已经说过的那样,要创建

LocalDate
,您需要 year,它不在输入
String
中。它只有星期几

要获得完整的

LocalDate
,您需要解析并找到,其中此日/月组合与星期几匹配。

当然,您可以忽略星期几并假设日期始终为当前;在这种情况下,其他答案已经提供了解决方案。但如果你想找到与星期几完全匹配的年份,你必须循环直到找到它。

我还创建了一个带有

java.util.Locale
的格式化程序,以明确表示我想要英文的 monthday of week 名称。如果您不指定区域设置,它将使用系统的默认设置,并且不能保证始终为英语(并且即使在运行时也可以在不通知的情况下进行更改)。

DateTimeFormatter formatter = new DateTimeFormatterBuilder()
    .parseCaseInsensitive()
    .append(DateTimeFormatter.ofPattern("EEEE MMMM d"))
    // use English Locale to correctly parse month and day of week
    .toFormatter(Locale.ENGLISH);
// parse input
TemporalAccessor parsed = formatter.parse("TUESDAY JULY 25");
// get month and day
MonthDay md = MonthDay.from(parsed);
// get day of week
DayOfWeek dow = DayOfWeek.from(parsed);
LocalDate date;
// start with some arbitrary year, stop at some arbitrary value
for(int year = 2017; year > 1970; year--) {
    // get day and month at the year
    date = md.atYear(year);
    // check if the day of week is the same
    if (date.getDayOfWeek() == dow) {
        // found: 'date' is the correct LocalDate
        break;
    }
}

在此示例中,我从 2017 年开始,并尝试查找直到 1970 年的日期,但您可以适应适合您的用例的值。

您还可以使用

Year.now().getValue()
获取当前年份(而不是某个固定的任意值)。


13
投票

LocalDate
的文档说,

LocalDate 是一个不可变的日期时间对象,表示日期, 通常被视为年-月-日。例如,值“10 月 2 日 2007”可以存储在 LocalDate 中。

在您的情况下,输入

String
缺少
LocalDate
的重要组成部分,即年份。你所拥有的基本上是月和日。因此,您可以使用适合该类型的类
MonthDay
。使用它您的代码可以修改为:

DateTimeFormatter formatter = new DateTimeFormatterBuilder()
                .parseCaseInsensitive()
                .append(DateTimeFormatter.ofPattern("EEEE MMMM d"))
                .toFormatter();

 MonthDay monthDay = MonthDay.parse(stringDate, formatter);
 LocalDate parsedDate = monthDay.atYear(2017); // or whatever year you want it at
 DateTimeFormatter formatter2 = DateTimeFormatter.ofPattern("MM/d/yyyy");

 String formattedStringDate = parsedDate.format(formatter2);
 System.out.println(formattedStringDate); //For "TUESDAY JULY 25" input, it gives the output 07/25/2017 

4
投票

这是您需要实施的微小更改:

private static String convertDate(String stringDate) 
{
    //from EEEE MMMM d -> MM/dd/yyyy

    DateTimeFormatter formatter = new DateTimeFormatterBuilder().appendPattern("EEEE MMMM dd")
                                        .parseDefaulting(ChronoField.YEAR, 2017)
                                        .toFormatter();

    LocalDate parsedDate = LocalDate.parse(stringDate, formatter);
    DateTimeFormatter formatter2 = DateTimeFormatter.ofPattern("MM/d/yyyy");

    String formattedStringDate = parsedDate.format(formatter2);

    return formattedStringDate;
}
  1. 使用

    .parseDefaulting(ChronoField.YEAR, 2017)

  2. 在格式化程序中添加默认的时间年份
  3. 使用参数

    "Tuesday July 25"
    调用该方法,如下所示
    convertDate("Tuesday July 25");


0
投票

这很有趣,它帮助我理解了 java.time.LocalTime 需要 HH:mm:ss 跳过 Hrs 是行不通的。

//Works
LocalTime time1 = LocalTime.parse("10:15:30", DateTimeFormatter.ofPattern("HH:mm:ss"));
        LocalTime time2 = LocalTime.parse("12:00:00", DateTimeFormatter.ofPattern("HH:mm:ss"));
//Fails
LocalTime time1 = LocalTime.parse("15:30", DateTimeFormatter.ofPattern("mm:ss"));
        LocalTime time2 = LocalTime.parse("00:00", DateTimeFormatter.ofPattern("mm:ss"));

-1
投票

另一种选择是执行以下操作(就像其他有点hacky的答案一样),当然假设您希望日期落在当年:

LocalDate localDate = LocalDate.parse(stringDate + " " +LocalDate.now().getYear(), DateTimeFormatter.ofPattern("EEEE MMMM d");
© www.soinside.com 2019 - 2024. All rights reserved.