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 is an immutable date-time object that represents a date,
often viewed as year-month-day. For example, the value "2nd October
2007" can be stored in a LocalDate.
在您的情况下,输入 String
缺少 LocalDate
的重要组成部分,即年份。你所拥有的基本上是月份和日期。因此,您可以使用适合 MonthDay
的 class。使用你的代码可以修改为:
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
这是您需要实施的小改动:
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;
}
使用.parseDefaulting(ChronoField.YEAR, 2017)
在格式化程序中添加默认的实际年份
像这样使用参数 "Tuesday July 25"
调用方法 convertDate("Tuesday July 25");
另一种选择是执行以下操作(就像其他答案一样有点老套),当然假设您希望日期落在当年:
LocalDate localDate = LocalDate.parse(stringDate + " " +LocalDate.now().getYear(), DateTimeFormatter.ofPattern("EEEE MMMM d");
正如其他答案所说,要创建 LocalDate
,您需要 year,它不在输入 String
中。它只有天、月和星期几。
要获得完整的 LocalDate
,您需要解析 天 和 月 并找到 年,其中此 day/month 组合与 星期几 .
匹配
当然你可以忽略星期几并假设日期总是在当前年份;在这种情况下,其他答案已经提供了解决方案。但是如果你想找到与星期几完全匹配的年,你必须循环直到找到它。
我还创建了一个带有 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()
.
获取当前年份(而不是某个固定的任意值)
我正在尝试将 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 is an immutable date-time object that represents a date, often viewed as year-month-day. For example, the value "2nd October 2007" can be stored in a LocalDate.
在您的情况下,输入 String
缺少 LocalDate
的重要组成部分,即年份。你所拥有的基本上是月份和日期。因此,您可以使用适合 MonthDay
的 class。使用你的代码可以修改为:
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
这是您需要实施的小改动:
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;
}
使用
.parseDefaulting(ChronoField.YEAR, 2017)
在格式化程序中添加默认的实际年份
像这样使用参数
"Tuesday July 25"
调用方法convertDate("Tuesday July 25");
另一种选择是执行以下操作(就像其他答案一样有点老套),当然假设您希望日期落在当年:
LocalDate localDate = LocalDate.parse(stringDate + " " +LocalDate.now().getYear(), DateTimeFormatter.ofPattern("EEEE MMMM d");
正如其他答案所说,要创建 LocalDate
,您需要 year,它不在输入 String
中。它只有天、月和星期几。
要获得完整的 LocalDate
,您需要解析 天 和 月 并找到 年,其中此 day/month 组合与 星期几 .
当然你可以忽略星期几并假设日期总是在当前年份;在这种情况下,其他答案已经提供了解决方案。但是如果你想找到与星期几完全匹配的年,你必须循环直到找到它。
我还创建了一个带有 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()
.