I need to convert strings of pattern 'YYYY0ww' to dates - based on US calendar (minimial days in week = 1, first day of the week = Sunday). Examples: 2020051, 2020052,...
Currently I'm using the following approach for building appropriate formatters (using java.time packages):
DateTimeFormatter weekFormat = DateTimeFormatterBuilder()
.parseDefaulting(ChronoField.DAY_OF_WEEK, WeekFields.SUNDAY_START.getFirstDayOfWeek().getValue())
.appendValue(WeekFields.SUNDAY_START.weekBasedYear(), 4)
.appendValue(WeekFields.SUNDAY_START.weekOfWeekBasedYear(), 3).parseStrict().toFormatter();
DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern("yyyyMMdd").withLocale(Locale.US);
The resolved date for a given week must be based on the Sunday of the given week.
It seems there's an obscure bug because one the following tests fails:
TestCase.assertEquals("20201213", LocalDate.parse("2020051", weekFormat).format(dateFormat)); // success
TestCase.assertEquals("20201220", LocalDate.parse("2020052", weekFormat).format(dateFormat)); // success
TestCase.assertEquals("20201227", LocalDate.parse("2020053", weekFormat).format(dateFormat)); // fail - parsed date contains year=2020, month=12, day=20 which would be CW 52/2020.
TestCase.assertEquals("20210103", LocalDate.parse("2021001", weekFormat).format(dateFormat)); // success
According to https://www.calendar-365.com/2020-calendar.html there exists a week 53 in 2020 in the US calendar - so "2020053" should be 20201227.
I already tried to apply .withResolverStyle(ResolverStyle.LENIENT) on the week formatter (because I noticed in the JDK implementation that strict parsing for some reason clamps sometimes - see WeekFields.ofWeekBasedYear() ). This makes the CW 53/2020 case work but then the test for "2021001" fails in a similar manner:
TestCase.assertEquals("20201213", LocalDate.parse("2020051", weekFormat).format(dateFormat)); // success
TestCase.assertEquals("20201220", LocalDate.parse("2020052", weekFormat).format(dateFormat)); // success
TestCase.assertEquals("20201227", LocalDate.parse("2020053", weekFormat).format(dateFormat)); // success
TestCase.assertEquals("20210103", LocalDate.parse("2021001", weekFormat).format(dateFormat)); // fail - parsed date contains year=2020, month=12, day=27 which would be CW 53/2020.
I'm confused that it's so tricky to get week to date conversion correct for non-ISO8601 calendars - I think this use-case is not very exotic.
Would appreciate feedback why my approach does not deliver correct results.
Update: after thinking more about this - I think I might have trapped into incorrectly believing that there is a calendar week 53 in US calendars in certain years. At least the linked websites mentioned CW 53. But based on the rule that the first week of the year is the week (starting with Sunday) which covers January 1st... probably means that there's never a calendar week 53 (and some websites got it wrong).