无法使用 DateTimeFormatter 解析月+日
Unable to parse a Month+day using DateTimeFormatter
我试着查看这个 link 来寻找灵感:
但是,当我尝试将字符串 "Mon 21st May" 解析为 "Monday 21st May" - 全日名称、日期编号和完整月份时出现错误。
Exception in thread "main" java.time.format.DateTimeParseException:
Text 'Mon 21st May' could not be parsed at index 0 at
java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:1949)
at
java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1851)
at java.time.LocalDate.parse(LocalDate.java:400) at
HelloWorld.main(HelloWorld.java:45)
代码如下:
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
// one class needs to have a main() method
public class HelloWorld
{
// arguments are passed using the text field below this editor
public static void main(String[] args) throws Exception
{
String str = "Mon 21st May";
DateTimeFormatter parseFormatter = DateTimeFormatter.ofPattern("EEEE d['st']['nd']['rd']['th'] MMMM", Locale.ENGLISH);
LocalDate datetext = LocalDate.parse(str, parseFormatter);
}
}
更新:
这是我按照建议尝试过的最新代码,我更改了字符串以查看问题是否与此有关,下面是我现在收到的错误。看起来它知道日期,只是无法解析它:
public static void main(String[] args) throws Exception
{
String str = "Tue 21st May";
DateTimeFormatter parseFormatter = DateTimeFormatter.ofPattern("EEE d['st']['nd']['rd']['th'] MMMM", Locale.ENGLISH);
LocalDate datetext = LocalDate.parse(str, parseFormatter);
}
}
错误:
Exception in thread "main" java.time.format.DateTimeParseException:
Text 'Tue 21st May' could not be parsed: Unable to obtain LocalDate from
TemporalAccessor: {DayOfWeek=2, DayOfMonth=21, MonthOfYear=5},ISO of
type java.time.format.Parsed at
java.time.format.DateTimeFormatter.createError(DateTimeFormatter.java:1920)
at
java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1855)
at java.time.LocalDate.parse(LocalDate.java:400) at
HelloWorld.main(HelloWorld.java:26) Caused by:
java.time.DateTimeException: Unable to obtain LocalDate from
TemporalAccessor: {DayOfWeek=2, DayOfMonth=21, MonthOfYear=5},ISO of
type java.time.format.Parsed at
java.time.LocalDate.from(LocalDate.java:368) at
java.time.format.Parsed.query(Parsed.java:226) at
java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1851)
... 2 more
MonthDay
如果你想解析没有年份的月份和日期,使用MonthDay
:
String str = "Mon 21st May";
DateTimeFormatter parseFormatter = DateTimeFormatter.ofPattern("EEE d['st']['nd']['rd']['th'] MMMM", Locale.ENGLISH);
MonthDay md = MonthDay.parse(str, parseFormatter);
System.out.println(md);
输出为:
--05-21
前导破折号表示缺席年份。格式模式字符串中的 EEEE
是星期几的全名,例如星期一或星期二。对于缩写,您需要 E
、EE
或 EEE
.
LocalDate
如果你想要 LocalDate
,你需要以某种方式提供一年。一种选择是:
LocalDate datetext = md.atYear(Year.now(ZoneId.of("Europe/London")).getValue());
System.out.println(datetext);
2019-05-21
不过,这不会验证月份中的第几天。为此:
String str = "Tue 21st May";
DateTimeFormatter parseFormatter = new DateTimeFormatterBuilder()
.appendPattern("EEE d['st']['nd']['rd']['th'] MMMM")
.parseDefaulting(ChronoField.YEAR, Year.now(ZoneId.of("Europe/London")).getValue())
.toFormatter(Locale.ENGLISH);
LocalDate datetext = LocalDate.parse(str, parseFormatter);
2019-05-21
在您提问的评论中:
What about if I want to output it as Tuesday 21 May?
这是一个新问题,已经讨论过很多次了,但是没关系。
DateTimeFormatter outputFormatter = DateTimeFormatter.ofPattern("EEEE d MMMM", Locale.ENGLISH);
System.out.println(datetext.format(outputFormatter));
Tuesday 21 May
从星期几检测年份
I may not know the year, as in I am trying to view dates in an
application but some dates may be this year, some may fall over to
next year but these dates don't have a year supplied
以下完整示例假定日期在从今天算起的未来 3 年内,并检测星期几正确的年份。成功后,它会以您想要的格式打印。
String str = "Wed 20th May";
ZoneId zone = ZoneId.of("Europe/London");
LocalDate today = LocalDate.now(zone);
int currentYear = today.getYear();
LocalDate datetext = null;
final int maxYearsFromToday = 3;
for (int year = currentYear; year <= currentYear + maxYearsFromToday; year++) {
DateTimeFormatter parseFormatter = new DateTimeFormatterBuilder()
.appendPattern("EEE d['st']['nd']['rd']['th'] MMMM")
.parseDefaulting(ChronoField.YEAR, year)
.toFormatter(Locale.ENGLISH);
try {
datetext = LocalDate.parse(str, parseFormatter);
System.out.println("Day of week matched for year " + year);
break;
} catch (DateTimeParseException dtpe) {
// Ignore, try next year
}
}
DateTimeFormatter outputFormatter = DateTimeFormatter.ofPattern("EEEE d MMMM", Locale.ENGLISH);
if (datetext == null) {
System.out.println("Could not parse date;"
+ " possibly the day of week didn’t match for any year in the range "
+ currentYear + " through " + (currentYear + maxYearsFromToday));
} else if (datetext.isBefore(today) || datetext.isAfter(today.plusYears(maxYearsFromToday))) {
System.out.println("Date is out of range");
} else {
System.out.println("Successfully parsed: " + datetext.format(outputFormatter));
}
Day of week matched for year 2020
Successfully parsed: Wednesday 20 May
现在是 2019 年 5 月 21 日星期二。下面的代码有效。
String str = "Tue 21st May 2019";
DateTimeFormatter parseFormatter = DateTimeFormatter.ofPattern("EEE d['st']['nd']['rd']['th'] MMMM yyyy", Locale.ENGLISH);
LocalDate datetext = LocalDate.parse(str, parseFormatter);
这是我搜索正确年份的代码:
在不知道星期几的情况下,您有 6/7 的机会将日期解析为错误的年份。但是,如果您知道日期名称,那么您可以搜索 7 年范围以找到正确的年份。
假设您有一个类似于以下之一的日期:
Wednesday, May 27
WED 5/27
格式化程序如:
DateTimeFormatter visibleButtonFormat = new DateTimeFormatterBuilder()
.parseCaseInsensitive()
.appendPattern("EEE M/dd")
.toFormatter(Locale.US);
DateTimeFormatter accessibleFormat = DateTimeFormatter.ofPattern("EEEE, MMMM dd");
然后,您可以像这样解析 MonthDay:
MonthDay monthDay = MonthDay.parse(dateText, oneOfTheAboveFormatters);
然后,您可以搜索正确的年份。在这种情况下是 2020 年:
private static int findYearMatchingMonthDay(String dateText, MonthDay monthDay) {
for(int checkYear = 2020; checkYear >= 2016; checkYear--) {
LocalDate localDate = LocalDate.of(checkYear, monthDay.getMonth(), monthDay.getDayOfMonth());
String shortDay = localDate.getDayOfWeek().getDisplayName(TextStyle.SHORT, Locale.US).toUpperCase();
if (shortDay.equals(dateText.substring(0,3))) {
ConsoleUtils.logDebug("Assuming schedule buttons within year: " + checkYear);
return checkYear;
}
}
return Year.now().getValue();
}
我试着查看这个 link 来寻找灵感:
但是,当我尝试将字符串 "Mon 21st May" 解析为 "Monday 21st May" - 全日名称、日期编号和完整月份时出现错误。
Exception in thread "main" java.time.format.DateTimeParseException: Text 'Mon 21st May' could not be parsed at index 0 at java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:1949) at java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1851) at java.time.LocalDate.parse(LocalDate.java:400) at HelloWorld.main(HelloWorld.java:45)
代码如下:
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
// one class needs to have a main() method
public class HelloWorld
{
// arguments are passed using the text field below this editor
public static void main(String[] args) throws Exception
{
String str = "Mon 21st May";
DateTimeFormatter parseFormatter = DateTimeFormatter.ofPattern("EEEE d['st']['nd']['rd']['th'] MMMM", Locale.ENGLISH);
LocalDate datetext = LocalDate.parse(str, parseFormatter);
}
}
更新:
这是我按照建议尝试过的最新代码,我更改了字符串以查看问题是否与此有关,下面是我现在收到的错误。看起来它知道日期,只是无法解析它:
public static void main(String[] args) throws Exception
{
String str = "Tue 21st May";
DateTimeFormatter parseFormatter = DateTimeFormatter.ofPattern("EEE d['st']['nd']['rd']['th'] MMMM", Locale.ENGLISH);
LocalDate datetext = LocalDate.parse(str, parseFormatter);
}
}
错误:
Exception in thread "main" java.time.format.DateTimeParseException: Text 'Tue 21st May' could not be parsed: Unable to obtain LocalDate from TemporalAccessor: {DayOfWeek=2, DayOfMonth=21, MonthOfYear=5},ISO of type java.time.format.Parsed at java.time.format.DateTimeFormatter.createError(DateTimeFormatter.java:1920) at java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1855) at java.time.LocalDate.parse(LocalDate.java:400) at HelloWorld.main(HelloWorld.java:26) Caused by: java.time.DateTimeException: Unable to obtain LocalDate from TemporalAccessor: {DayOfWeek=2, DayOfMonth=21, MonthOfYear=5},ISO of type java.time.format.Parsed at java.time.LocalDate.from(LocalDate.java:368) at java.time.format.Parsed.query(Parsed.java:226) at java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1851) ... 2 more
MonthDay
如果你想解析没有年份的月份和日期,使用MonthDay
:
String str = "Mon 21st May";
DateTimeFormatter parseFormatter = DateTimeFormatter.ofPattern("EEE d['st']['nd']['rd']['th'] MMMM", Locale.ENGLISH);
MonthDay md = MonthDay.parse(str, parseFormatter);
System.out.println(md);
输出为:
--05-21
前导破折号表示缺席年份。格式模式字符串中的 EEEE
是星期几的全名,例如星期一或星期二。对于缩写,您需要 E
、EE
或 EEE
.
LocalDate
如果你想要 LocalDate
,你需要以某种方式提供一年。一种选择是:
LocalDate datetext = md.atYear(Year.now(ZoneId.of("Europe/London")).getValue());
System.out.println(datetext);
2019-05-21
不过,这不会验证月份中的第几天。为此:
String str = "Tue 21st May";
DateTimeFormatter parseFormatter = new DateTimeFormatterBuilder()
.appendPattern("EEE d['st']['nd']['rd']['th'] MMMM")
.parseDefaulting(ChronoField.YEAR, Year.now(ZoneId.of("Europe/London")).getValue())
.toFormatter(Locale.ENGLISH);
LocalDate datetext = LocalDate.parse(str, parseFormatter);
2019-05-21
在您提问的评论中:
What about if I want to output it as Tuesday 21 May?
这是一个新问题,已经讨论过很多次了,但是没关系。
DateTimeFormatter outputFormatter = DateTimeFormatter.ofPattern("EEEE d MMMM", Locale.ENGLISH);
System.out.println(datetext.format(outputFormatter));
Tuesday 21 May
从星期几检测年份
I may not know the year, as in I am trying to view dates in an application but some dates may be this year, some may fall over to next year but these dates don't have a year supplied
以下完整示例假定日期在从今天算起的未来 3 年内,并检测星期几正确的年份。成功后,它会以您想要的格式打印。
String str = "Wed 20th May";
ZoneId zone = ZoneId.of("Europe/London");
LocalDate today = LocalDate.now(zone);
int currentYear = today.getYear();
LocalDate datetext = null;
final int maxYearsFromToday = 3;
for (int year = currentYear; year <= currentYear + maxYearsFromToday; year++) {
DateTimeFormatter parseFormatter = new DateTimeFormatterBuilder()
.appendPattern("EEE d['st']['nd']['rd']['th'] MMMM")
.parseDefaulting(ChronoField.YEAR, year)
.toFormatter(Locale.ENGLISH);
try {
datetext = LocalDate.parse(str, parseFormatter);
System.out.println("Day of week matched for year " + year);
break;
} catch (DateTimeParseException dtpe) {
// Ignore, try next year
}
}
DateTimeFormatter outputFormatter = DateTimeFormatter.ofPattern("EEEE d MMMM", Locale.ENGLISH);
if (datetext == null) {
System.out.println("Could not parse date;"
+ " possibly the day of week didn’t match for any year in the range "
+ currentYear + " through " + (currentYear + maxYearsFromToday));
} else if (datetext.isBefore(today) || datetext.isAfter(today.plusYears(maxYearsFromToday))) {
System.out.println("Date is out of range");
} else {
System.out.println("Successfully parsed: " + datetext.format(outputFormatter));
}
Day of week matched for year 2020 Successfully parsed: Wednesday 20 May
现在是 2019 年 5 月 21 日星期二。下面的代码有效。
String str = "Tue 21st May 2019";
DateTimeFormatter parseFormatter = DateTimeFormatter.ofPattern("EEE d['st']['nd']['rd']['th'] MMMM yyyy", Locale.ENGLISH);
LocalDate datetext = LocalDate.parse(str, parseFormatter);
这是我搜索正确年份的代码:
在不知道星期几的情况下,您有 6/7 的机会将日期解析为错误的年份。但是,如果您知道日期名称,那么您可以搜索 7 年范围以找到正确的年份。
假设您有一个类似于以下之一的日期:
Wednesday, May 27
WED 5/27
格式化程序如:
DateTimeFormatter visibleButtonFormat = new DateTimeFormatterBuilder()
.parseCaseInsensitive()
.appendPattern("EEE M/dd")
.toFormatter(Locale.US);
DateTimeFormatter accessibleFormat = DateTimeFormatter.ofPattern("EEEE, MMMM dd");
然后,您可以像这样解析 MonthDay:
MonthDay monthDay = MonthDay.parse(dateText, oneOfTheAboveFormatters);
然后,您可以搜索正确的年份。在这种情况下是 2020 年:
private static int findYearMatchingMonthDay(String dateText, MonthDay monthDay) {
for(int checkYear = 2020; checkYear >= 2016; checkYear--) {
LocalDate localDate = LocalDate.of(checkYear, monthDay.getMonth(), monthDay.getDayOfMonth());
String shortDay = localDate.getDayOfWeek().getDisplayName(TextStyle.SHORT, Locale.US).toUpperCase();
if (shortDay.equals(dateText.substring(0,3))) {
ConsoleUtils.logDebug("Assuming schedule buttons within year: " + checkYear);
return checkYear;
}
}
return Year.now().getValue();
}