Skip to main content

Java Date Formatting Bug: YYYY vs yyyy Explained

Updated 4 min readMarkdown
Java Date Formatting Bug: YYYY vs yyyy Explained

In Java date formatting, uppercase YYYY represents the week-based year, while lowercase yyyy represents the calendar year. Using YYYY can cause dates in late December to print as the following calendar year depending on the system locale, leading to silent end-of-year production bugs. I always recommend auditing date patterns for lowercase yyyy.

I see this exact bug hit production every single year around late December: an application suddenly starts printing dates from the future. You haven't accidentally built a time machine; you've just fallen into one of Java's most notorious date-formatting traps—the subtle difference between uppercase YYYY and lowercase yyyy.

What is the difference between YYYY and yyyy in Java date formatting?

In Java, lowercase yyyy formats the standard calendar year, whereas uppercase YYYY formats the week-based year (or week year). I strictly reserve YYYY for ISO week-numbering formats and use yyyy for virtually every standard application date pattern.

The calendar year increments predictably at midnight on January 1st. In contrast, the week-based year ties dates to full seven-day week cycles dictated by locale rules. Because a single week can span two calendar years, ISO 8601 and regional calendar definitions assign the entire week to whichever year contains the majority (or specific boundary days) of that week.

How does the YYYY week year bug break dates in production?

The YYYY pattern calculates the year based on the week to which a day belongs, where week one starts in whichever week contains January 1st. If January 1st lands mid-week, days in late December get dragged into the upcoming year.

Let's look at a concrete hypothetical scenario using the US locale, where calendar weeks begin on Sunday:

  1. January 1, 2027 falls on a Friday.
  2. The week containing January 1, 2027 starts on Sunday, December 27, 2026.
  3. Because January 1st lands within that week, the US locale assigns the whole week to week-year 2027.
  4. If you format December 27, 2026 using YYYY, Java outputs 2027.

I've reproduced this exact behavior in a few lines of code:

LocalDate date = LocalDate.of(2026, 12, 27);

// WRONG: Week year prints 2027 in US locale
DateTimeFormatter wrongFormat = DateTimeFormatter.ofPattern("YYYY-MM-dd");
System.out.println(date.format(wrongFormat)); // 2027-12-27

// RIGHT: Calendar year prints 2026
DateTimeFormatter rightFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd");
System.out.println(date.format(rightFormat)); // 2026-12-27

How do locale rules affect Java date format specifiers?

System locale dictates both the start day of the week and the minimum threshold of days required to establish week one of a year. Because these rules vary by country, code using YYYY can produce completely different output depending on where your application runs.

I find that localized date shifts are particularly dangerous in microservices deployed across multiple regions. What renders correctly on a local dev machine running under one locale might flip to the wrong year on a production server configured with another.

Format Specifier Description Example Pattern Output for Dec 27, 2026 (US Locale)
yyyy Calendar Year yyyy-MM-dd 2026-12-27
YYYY Week-Based Year YYYY-MM-dd 2027-12-27
ww Week of Week-Based Year YYYY-ww 2027-01

Frequently Asked Questions

Why does Java provide YYYY if it causes errors?

Uppercase YYYY isn't a defect; it exists specifically to support ISO 8601 week-date formatting (like 2027-W01-5). I only ever use YYYY alongside week-of-year specifiers like ww when building reports grouped strictly by calendar weeks.

Do other programming languages have the YYYY vs yyyy issue?

Yes, many date handling libraries across JavaScript, Swift, and C# follow Unicode Technical Standard #35. I've spotted this same format mismatch in libraries like Moment.js and date-fns when developers accidentally type uppercase format strings.

How can I catch YYYY formatting bugs before going to production?

I recommend configuring static analysis tools like SpotBugs, ArchUnit, or SonarQube in your build pipeline. These tools include dedicated linter rules that flag uppercase YYYY inside SimpleDateFormat or DateTimeFormatter patterns immediately.

Cheers, Doogal

No comments yet. Be the first to comment.