DateTimeFormatter pattern Y prints the week-based year, which can differ from the calendar year printed by u.
Java DateTimeFormatter week-year Y versus calendar year u
Keep identifiers out of the wrong calendar
A date near New Year can belong to the first ISO week of the following week-based year. If an invoice ID uses YYYY-MM-dd by mistake, its year can disagree with its month and day. Use uuuu-MM-dd for a calendar date, or explicitly format a week date when that is the intended business identifier.
The fixture fixes Locale.UK so week conventions do not depend on the machine default. December 30, 2019 has calendar year 2019 but belongs to week 1 of week-based year 2020. Strict input parsing covers validation after choosing the correct fields.
Make locale part of the contract
Week numbering varies by locale. A persisted week identifier needs a declared convention; changing the JVM default locale must not change existing keys. Prefer explicit WeekFields or a fixed formatter locale, and test year boundaries.
Working program
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
public class ShipmentWeekIdentifier {
public static void main(String[] args) {
LocalDate shipped = LocalDate.of(2019, 12, 30);
DateTimeFormatter calendar = DateTimeFormatter.ofPattern("uuuu-MM-dd", Locale.UK);
DateTimeFormatter week = DateTimeFormatter.ofPattern("YYYY-'W'ww-e", Locale.UK);
System.out.println(shipped.format(calendar));
System.out.println(shipped.format(week));
}
}Output
2019-12-30
2020-W01-1Cost and ownership
Formatting a fixed date uses bounded application storage and work. Persisted identifiers carry a larger migration cost if the wrong year field was used; changing the formatter later does not repair keys already issued.
Common Mistakes
- Do not use YYYY for a calendar-year date field.
- Do not rely on the process default locale for persisted week keys.
- Do not change an existing week convention without a migration plan.
Read next
Java strict date parsing: reject impossible calendar input, Java date and time: local schedules versus instants, Java YearMonth.atEndOfMonth: calculate a month boundary without guessed days, Java ResourceBundle: locale fallback and missing message keys.
