Amos M. Carpenter Amos M. Carpenter - 2 months ago 5
Java Question

Java Time's week-of-week-based-year pattern parsing with DateTimeFormatter

I need to output the current date in the format

week-based-year
-
week-of-week-based-year
, i.e. using the ISO week date where the week always starts on a Monday and the first week of the year is the first one that has at least four days in January (so the week with the first Thursday in January).

Since 31 December 2015 was a Thursday, the Friday through Sunday, i.e. 1st through 3rd of January 2016, all belong in the 53rd week of 2015 (a "long year"), and the first week of 2016 starts on Monday, 4 January.

From the DateTimeFormatter spec, I would have expected that I can just use the pattern
YYYY-ww
to do that (
Y
is
week-based-year
and
w
is
week-of-week-based-year
).

However, when I try something like the following simplified test case:

String dateString = "2016-01-03";
LocalDate date = LocalDate.parse(dateString, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
String expectedOutput = "2015-53";
String actualOutput = date.format(DateTimeFormatter.ofPattern("YYYY-ww"));
System.out.println("Parsing " + dateString + ", expected "
+ expectedOutput + " but got " + actualOutput);
System.out.println(dateString + " as ISO week date: "
+ date.format(DateTimeFormatter.ISO_WEEK_DATE));


I get this:


Parsing 2016-01-03, expected 2015-53 but got 2016-02


2016-01-03 as ISO week date: 2015-W53-7



So using the built-in
ISO_WEEK_DATE
formatter does what I expected, but using the pattern
YYYY-ww
seems to give me the calendar year and week.

Have I misunderstood something about ISO week dates, or is there an error in my code, or... dare I say it... is this a bug in the
java.time
library (as was the case for this question)?

I know I could work around this using a custom formatter like below, but in my case I really need this to work using a pattern.

new DateTimeFormatterBuilder()
.parseCaseInsensitive()
.appendValue(IsoFields.WEEK_BASED_YEAR, 4, 10, SignStyle.EXCEEDS_PAD)
.appendLiteral("-")
.appendValue(IsoFields.WEEK_OF_WEEK_BASED_YEAR, 2)
.toFormatter();

Answer

The documentation of DateTimeFormatterBuilder specifies that "Y" appends the localized week-based year. Thus, the meaning of the week-based year and week fields will depend on the locale set in the formatter.