# 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:

```java
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
