Understanding the Difference Between yyyy and YYYY, and dd and DD in Java Date Formatting
This article explains how using uppercase YYYY and DD in Java date patterns produces week‑based year and day‑of‑year values, leading to unexpected results around year boundaries, and provides code examples and best‑practice recommendations to avoid these formatting bugs.
The author writes this post to record a bug that occurred when calculating the number of days between two dates across a new year, which caused incorrect production data because the test team did not simulate the scenario.
1 yyyy and YYYY
Below is a test demonstrating the difference between the lowercase yyyy and uppercase YYYY patterns.
@Test
public void testWeekBasedYear() {
Calendar calendar = Calendar.getInstance();
// 2019-12-31
calendar.set(2019, Calendar.DECEMBER, 31);
Date strDate1 = calendar.getTime();
// 2020-01-01
calendar.set(2020, Calendar.JANUARY, 1);
Date strDate2 = calendar.getTime();
// Uppercase YYYY
SimpleDateFormat formatYYYY = new SimpleDateFormat("YYYY/MM/dd");
System.out.println("2019-12-31 转 YYYY/MM/dd 格式: " + formatYYYY.format(strDate1));
System.out.println("2020-01-01 转 YYYY/MM/dd 格式: " + formatYYYY.format(strDate2));
// Lowercase yyyy
SimpleDateFormat formatyyyy = new SimpleDateFormat("yyyy/MM/dd");
System.out.println("2019-12-31 转 yyyy/MM/dd 格式: " + formatyyyy.format(strDate1));
System.out.println("2020-01-01 转 yyyy/MM/dd 格式: " + formatyyyy.format(strDate2));
}Output:
2019-12-31 转 YYYY/MM/dd 格式: 2020/12/31
2020-01-01 转 YYYY/MM/dd 格式: 2020/01/01
2019-12-31 转 yyyy/MM/dd 格式: 2019/12/31
2020-01-01 转 yyyy/MM/dd 格式: 2020/01/01The surprising result is that 2019-12-31 formatted with YYYY becomes 2020/12/31 . This happens because YYYY represents the week‑based year defined by ISO‑8601, i.e., the year of the Thursday of that week.
What is YYYY?
Java's DateTimeFormatter pattern "YYYY" gives you the week‑based‑year, (by default, ISO‑8601 standard) the year of the Thursday of that week.
Examples:
12/29/2019 formats to 2019 because that week still belongs to 2019.
12/30/2019 formats to 2020 because that week already belongs to 2020.
Thus, on 2019‑12‑31 the week‑based year is already 2020, so the formatted string shows 2020 while the month and day remain unchanged.
2 dd and DD
private static void tryit(int Y, int M, int D, String pat) {
DateTimeFormatter fmt = DateTimeFormatter.ofPattern(pat);
LocalDate dat = LocalDate.of(Y, M, D);
String str = fmt.format(dat);
System.out.printf("Y=%04d M=%02d D=%02d " +
"formatted with " +
"\"%s\" -> %s\n", Y, M, D, pat, str);
}
public static void main(String[] args) {
tryit(2020, 01, 20, "MM/DD/YYYY");
tryit(2020, 01, 21, "DD/MM/YYYY");
tryit(2020, 01, 22, "YYYY-MM-DD");
tryit(2020, 03, 17, "MM/DD/YYYY");
tryit(2020, 03, 18, "DD/MM/YYYY");
tryit(2020, 03, 19, "YYYY-MM-DD");
}Output:
Y=2020 M=01 D=20 formatted with "MM/DD/YYYY" -> 01/20/2020
Y=2020 M=01 D=21 formatted with "DD/MM/YYYY" -> 21/01/2020
Y=2020 M=01 D=22 formatted with "YYYY-MM-DD" -> 2020-01-22
Y=2020 M=03 D=17 formatted with "MM/DD/YYYY" -> 03/77/2020
Y=2020 M=03 D=18 formatted with "DD/MM/YYYY" -> 78/03/2020
Y=2020 M=03 D=19 formatted with "YYYY-MM-DD" -> 2020-03-79The last three dates are incorrect because the uppercase DD represents the day‑of‑year (the ordinal day within the year), not the day‑of‑month, leading to nonsensical results.
3 Conclusion
Remember that YYYY and yyyy , as well as DD and dd , are not interchangeable; using the wrong pattern can cause serious bugs.
This issue is not the author's responsibility.
Selected Java Interview Questions
A professional Java tech channel sharing common knowledge to help developers fill gaps. Follow us!
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.