I'm trying to parse a week-based-year and week-of-week-based-year from a string without any separator character. E.g. "201812" (week 12 of year 2018). Like this:
DateTimeFormatter formatter = new DateTimeFormatterBuilder()
.appendPattern("YYYYww")
.parseDefaulting(WeekFields.ISO.dayOfWeek(), 1)
.toFormatter();
LocalDate parse = LocalDate.parse("201803", formatter);
But this gives me:
java.time.format.DateTimeParseException: Text '201803' could not be parsed at index 0
If I add a space between the fields like so:
DateTimeFormatter formatter = new DateTimeFormatterBuilder()
.appendPattern("YYYY ww")
.parseDefaulting(WeekFields.ISO.dayOfWeek(), 1)
.toFormatter();
LocalDate parse = LocalDate.parse("2018 03", formatter);
It works fine, with result:
2018-01-15
Is this another bug like this one? Or am I missing something?
The workaround I found was building a custom formatter:
DateTimeFormatter yearWeekPattern = new DateTimeFormatterBuilder().appendValue(IsoFields.WEEK_BASED_YEAR, 4)
.appendValue(IsoFields.WEEK_OF_WEEK_BASED_YEAR, 2)
.parseDefaulting(WeekFields.ISO.dayOfWeek(), 1)
.toFormatter();
LocalDate.parse("201803", yearWeekPattern).atStartOfDay(ZoneId.systemDefault()).toInstant();
All weeks in the ISO-8601 Week-Based calendar have exactly 7 days, start on a Monday, and each week belongs to single year. Unlike the Gregorian calendar, there are no weeks that extend across years. Each ISO-8601 year is either a Long or a Short year, with 52 or 53 weeks depending on when the ISO-8601 year begins. Day.
“Week year” is intended to be used for week dates, e.g. “2015-W01-1”, but is often mistakenly used for calendar dates, e.g. 2014-12-29, in which case the year may be incorrect during the last week of the year. If you are formatting anything other than a week date, you should use the year specifier “yyyy” instead.
BASIC_ISO_DATE. The ISO date formatter that formats or parses a date without an offset, such as '20111203'. static DateTimeFormatter. ISO_DATE. The ISO date formatter that formats or parses a date with the offset if available, such as '2011-12-03' or '2011-12-03+01:00'.
Explanation of the pattern dd-MM-yy hh.
This is a known bug which has been fixed for Java-9.
If you are still on Java-8 and cannot move to Java-9 then
you are either out of luck
or you can use a 3rd-party-library.
Joda-Time: (uses "x" for week-based-year)
DateTimeFormatter formatter =
new DateTimeFormatterBuilder().appendPattern("xxxxww").toFormatter();
LocalDate joda = LocalDate.parse("201803", formatter);
System.out.println(joda); // 2018-01-15
A replacement for parseDefaulting()
is not available.
Time4J (my lib):
ChronoFormatter<CalendarWeek> f =
ChronoFormatter.ofPattern(
"YYYYww",
PatternType.CLDR,
Locale.ROOT,
CalendarWeek.chronology()
);
CalendarWeek cw = f.parse("201803");
java.time.LocalDate d = cw.at(Weekday.MONDAY).toTemporalAccessor();
System.out.println(d); // 2018-01-15
The replacement for parseDefaulting()
can be achieved if you set up the formatter not for the type CalendarWeek
but the basic type PlainDate
and use this general formatter method withDefault(...). Example:
ChronoFormatter<PlainDate> f =
ChronoFormatter
.ofDatePattern("YYYYww", PatternType.CLDR, Locale.ROOT)
.withDefault(PlainDate.DAY_OF_WEEK, Weekday.MONDAY);
PlainDate cw = f.parse("201803");
java.time.LocalDate d = cw.toTemporalAccessor();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With