Understanding the Difference Between yyyy and YYYY (and dd vs DD) in Java Date Formatting
This article explains why using uppercase YYYY or DD in Java date‑format patterns can produce incorrect results around year boundaries, demonstrates the bugs with concrete code examples, and clarifies the correct usage of lowercase yyyy and dd for calendar dates.
The author wrote this post to record a bug encountered when calculating the number of days between two dates across a year boundary, which caused incorrect production data.
While browsing a technical forum, a Java date‑handling bug was discovered: the difference between the pattern symbols yyyy and YYYY, as well as dd and DD.
Code Example 1
@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 result shows that formatting 2019-12-31 with YYYY/MM/dd yields 2020/12/31 because YYYY represents the ISO week‑based year, which for the last week of 2019 belongs to 2020.
Why does this happen?
According to ISO‑8601, the week‑based year can differ from the calendar year; the week containing 31 December 2019 is considered part of the 2020 week‑based year.
Difference Between 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
", 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 results are wrong because the uppercase DD represents the day‑of‑year (1‑365/366) rather than the day‑of‑month, leading to nonsensical dates.
Conclusion: YYYY and yyyy , as well as DD and dd , are not interchangeable; using the wrong pattern can cause subtle bugs in date calculations.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Big Data Technology & Architecture
Wang Zhiwu, a big data expert, dedicated to sharing big data technology.
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.
