Java SimpleDateFormat 年份轉換錯誤

Calendar calendar1 = new GregorianCalendar(2021, 11, 31);
System.out.println(new SimpleDateFormat("yyyy/MM/dd").format(calendar1.getTime())); // 2021/12/31
System.out.println(new SimpleDateFormat("YYYY/MM/dd").format(calendar1.getTime())); // 2022/12/31

Calendar calendar2 = new GregorianCalendar(2022, 11, 31);
System.out.println(new SimpleDateFormat("yyyy/MM/dd").format(calendar2.getTime())); // 2022/12/31
System.out.println(new SimpleDateFormat("YYYY/MM/dd").format(calendar2.getTime())); // 2022/12/31

System.out.println(calendar1.get(Calendar.WEEK_OF_YEAR)); // 1
System.out.println(calendar2.get(Calendar.WEEK_OF_YEAR)); // 53

calendar1 的轉換結果硬生生多了一年
而 calendar2 的轉換卻又正確
原來貓膩出現在 format 參數

大寫的 YYYY 是指 Week Year
同一週都算同年度
所以年末幾天可能併到下一年
而年初幾天可能併到上一年

2021/12/31 已經算在 2022 的第 1 週了
所以 Week Year 是 2022

2022/12/31 還是 2022 的第 53 週
所以 Week Year 一樣是 2022

小寫的 yyyy 才是 Calendar Year
也就是一般所講的年份
千萬不要用錯了


註:
一週的起算日也有相關的 API
calendar1.getFirstDayOfWeek(); // 1 SUNDAY
calendar1.setFirstDayOfWeek(Calendar.MONDAY);
起算日的不同當然也會影響 Week Year 的結果