NSDateFormatter
date formatting
YYYY vs yyyy
iOS development
Swift programming

Difference between 'YYYY' and 'yyyy' in NSDateFormatter

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

In NSDateFormatter and modern DateFormatter, yyyy and YYYY are not interchangeable. yyyy means calendar year, while YYYY means week-based year. Most date formatting bugs happen because developers use YYYY when they really mean the ordinary year number.

The difference usually appears near the start or end of a year. For dates that fall into the first or last ISO week of an adjacent year, YYYY can produce a year value that surprises you.

yyyy Means Calendar Year

Use yyyy when you want the normal year people expect on the calendar.

For example, December 31, 2023 should normally display as year 2023, and January 1, 2024 should normally display as 2024. That is what yyyy does.

swift
1import Foundation
2
3let formatter = DateFormatter()
4formatter.calendar = Calendar(identifier: .gregorian)
5formatter.locale = Locale(identifier: "en_US_POSIX")
6formatter.dateFormat = "yyyy-MM-dd"
7
8let date = ISO8601DateFormatter().date(from: "2024-01-01T00:00:00Z")!
9print(formatter.string(from: date))

This is the right format string for most app UI, APIs, logs, and filenames that use calendar dates.

YYYY Means Week-Based Year

YYYY is tied to week-based date systems, not the ordinary month-day calendar year. It is meaningful when you are formatting dates together with week-of-year fields.

That is why YYYY can differ from yyyy near year boundaries.

For example, a date at the end of December may belong to week 1 of the next week-based year, or a date at the start of January may still belong to the last week of the previous week-based year.

swift
1import Foundation
2
3let input = ISO8601DateFormatter().date(from: "2016-01-01T00:00:00Z")!
4
5let calendarYear = DateFormatter()
6calendarYear.calendar = Calendar(identifier: .gregorian)
7calendarYear.locale = Locale(identifier: "en_US_POSIX")
8calendarYear.dateFormat = "yyyy-MM-dd"
9
10let weekYear = DateFormatter()
11weekYear.calendar = Calendar(identifier: .gregorian)
12weekYear.locale = Locale(identifier: "en_US_POSIX")
13weekYear.dateFormat = "YYYY-'W'ww"
14
15print(calendarYear.string(from: input))
16print(weekYear.string(from: input))

The first formatter shows the regular date year. The second shows the week-based year and week number, which can reflect a different year classification.

When You Should Use Each One

Use yyyy for nearly all user-facing dates such as:

  • birthdays
  • invoice dates
  • event dates
  • filenames based on calendar dates
  • JSON strings representing ordinary dates

Use YYYY only when the output is intentionally week-based, typically alongside week fields such as ww.

If you are not formatting week numbers, YYYY is usually the wrong choice.

Why This Bug Is So Common

The bug is common because the letters look almost identical, and many developers reasonably assume uppercase and lowercase only change styling. In date formatting, they do not.

A format string like "YYYY-MM-dd" often appears to work for most of the year, then breaks around New Year’s Day. That makes the bug easy to miss in casual testing.

A Safe Formatter Setup

When formatting machine-readable dates, use a fixed locale as well.

swift
1import Foundation
2
3let formatter = DateFormatter()
4formatter.calendar = Calendar(identifier: .gregorian)
5formatter.locale = Locale(identifier: "en_US_POSIX")
6formatter.timeZone = TimeZone(secondsFromGMT: 0)
7formatter.dateFormat = "yyyy-MM-dd"

This avoids another class of subtle formatting bugs related to locale-specific behavior.

Common Pitfalls

The biggest mistake is using YYYY when you really mean calendar year. That usually produces wrong results only around year boundaries, which makes it easy to ship unnoticed.

Another mistake is mixing week-based year fields with month-day fields. If you use YYYY with MM and dd, the result can be logically inconsistent because the year is week-based while the month and day are calendar-based.

Developers also forget that date formatting symbols follow Unicode date-pattern rules, not ad hoc Apple-only conventions.

Finally, do not test this only with midyear dates. If the formatter contains year symbols, always test dates near late December and early January.

Summary

  • 'yyyy means calendar year.'
  • 'YYYY means week-based year.'
  • Use yyyy for ordinary dates almost all the time.
  • Use YYYY only for week-based representations, usually together with week numbers.
  • If a year-formatting bug appears only around New Year, check for accidental use of YYYY.

Course illustration
Course illustration

All Rights Reserved.