繁体   English   中英

Java:无法从TemporalAccessor获取LocalDate

[英]Java: Unable to obtain LocalDate from TemporalAccessor

我想一个的格式改变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)

LocalDate的文档说,那

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

正如其他答案已经说过的,要创建LocalDate您需要年份 ,而不是输入String 它只有一周中的 一天一个月一天

要获取完整的LocalDate ,您需要解析日期月份,并找到这一天/月组合与星期几匹配的年份

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

我也正在创建一个带有java.util.Locale的格式化程序,以明确表示我想用英文命名月份星期几 如果您没有指定语言环境,它将使用系统的默认设置,并且不保证始终为英语(即使在运行时也可以在不事先通知的情况下进行更改)。

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()获取当前年份(而不是某些固定的任意值Year.now().getValue()

以下是您需要实施的细微更改:

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. 使用参数"Tuesday July 25"调用方法,就像这个convertDate("Tuesday July 25");

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

LocalDate localDate = LocalDate.parse(stringDate + " " +LocalDate.now().getYear(), DateTimeFormatter.ofPattern("EEEE MMMM d");

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM