Why Using “YYYY” in SimpleDateFormat Breaks Dates Around New Year (and How to Fix It)
Around the 2020 New Year many Java applications displayed dates like 2020/12/31 due to a subtle bug in SimpleDateFormat when using the pattern "YYYY" instead of "yyyy", which can be reproduced, explained, and resolved with a simple pattern change.
Reproducing the Bug
The following Java program uses SimpleDateFormat with the pattern "YYYY-MM-dd HH:mm:ss" to parse the string "2020-1-1 13:12:12" and prints the parsed Date and the formatted result:
public class DateFormatBug {
public static void main(String[] args) throws ParseException {
printBugDate();
}
private static void printBugDate() throws ParseException {
SimpleDateFormat sdf = new SimpleDateFormat("YYYY-MM-dd HH:mm:ss");
Date date = sdf.parse("2020-1-1 13:12:12");
System.out.println(date);
String dateStr = sdf.format(date);
System.out.println(dateStr);
}
}Running this code prints:
Sun Dec 29 13:12:12 CST 2019
2020-12-29 13:12:12The parsed date is in 2019, while the formatted string shows December 29, 2020 – an incorrect result.
Extended Example
Parsing "2019-12-31 13:12:12" with the same pattern yields another wrong year:
private static void printBugDateExtend() throws ParseException {
SimpleDateFormat sdf = new SimpleDateFormat("YYYY-MM-dd HH:mm:ss");
Date date = sdf.parse("2019-12-31 13:12:12");
System.out.println(date);
String dateStr = sdf.format(date);
System.out.println(dateStr);
} Sun Dec 30 13:12:12 CST 2018
2019-12-30 13:12:12Both examples demonstrate that the year component is shifted.
Why It Happens
In SimpleDateFormat the pattern letter Y does **not** represent the calendar year; it denotes the *week‑based year* (ISO‑8601 week year). The week‑based year can differ from the calendar year at the start or end of a year, especially when the first week does not contain at least four days of the new year. This explains the off‑by‑one behavior for dates near New Year’s.
Official documentation (Javadoc) describes this behavior: https://docs.oracle.com/javase/8/docs/api/java/time/temporal/WeekFields.html
Fixing the Issue
Use the lowercase y pattern letter to represent the calendar year. Updating the format strings eliminates the bug:
private static void printDate() throws ParseException {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date date = sdf.parse("2020-1-1 13:12:12");
System.out.println(date);
String dateStr = sdf.format(date);
System.out.println(dateStr);
}
private static void printDateExtend() throws ParseException {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date date = sdf.parse("2019-12-31 13:12:12");
System.out.println(date);
String dateStr = sdf.format(date);
System.out.println(dateStr);
}Running the corrected code yields the expected output:
Wed Jan 01 13:12:12 CST 2020
2020-01-01 13:12:12
Tue Dec 31 13:12:12 CST 2019
2019-12-31 13:12:12Takeaway
Never use the uppercase Y for the year in date‑time patterns unless the week‑based year is explicitly required. Prefer lowercase y to avoid subtle cross‑year bugs in production systems.
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.
Senior Brother's Insights
A public account focused on workplace, career growth, team management, and self-improvement. The author is the writer of books including 'SpringBoot Technology Insider' and 'Drools 8 Rule Engine: Core Technology and Practice'.
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.
