How to Use This Tool
Pick a token style, type a pattern, and see it rendered. Testing takes a second and catches the mistakes that reasoning about the letters does not.
The one that ruins New Year
In Unicode date patterns — used by Java, .NET, ICU and Moment-style libraries —
yyyy is the calendar year and YYYY is the ISO week-numbering
year. They are different things.
The ISO week-numbering year follows whole weeks. A week belongs to the year containing its Thursday, so
the last few days of December can belong to the following year's week 1. On 31 December 2019 the
week-numbering year is 2020, and YYYY-MM-DD renders 2020-12-31.
The reason this survives testing is that the two agree on roughly 362 days out of 365. Code written and tested in March looks perfect, ships, and produces wrong dates for a few days each January — which is why a wave of date bugs appears in the first week of the year, every year.
Unless you are deliberately formatting an ISO week date, you want lowercase yyyy.
Two more that behave the same way
Dagainstd. In Unicode patternsdis the day of the month andDis the day of the year.DDrenders 05 on 5 January and 152 in June, so it also passes early-January testing.mmagainstMM. In Unicode patterns lowercasemmis minutes and uppercaseMMis months. In strftime it is the opposite way round:%mis the month and%Mis minutes. The same habit produces the wrong result in the other system.
The two systems
- strftime uses percent-prefixed letters:
%Y-%m-%d %H:%M:%S. Used by C, Python, PHP'sstrftime, shelldateand most Unix tooling. The percent prefix makes literal text unambiguous, which is its main advantage. - Unicode patterns use repeated letters:
yyyy-MM-dd HH:mm:ss. Used by Java, .NET, ICU and libraries modelled on them. Literal text must be quoted with single quotes, which is why ISO patterns contain'T'.
The number of repeats usually means width: M is 1 or 2 digits, MM is always
2, MMM is a short name and MMMM is the full one.
When not to use a pattern at all
Two cases where hand-writing a format is the wrong instinct:
- Machine-readable output. Use ISO 8601 and let the library produce it. It is unambiguous, it sorts as text, and every parser accepts it.
- Text a person reads. Use the platform's locale formatting. Date order, month names,
separators and the position of the year all differ by locale, and a hand-written
MM/DD/YYYYis wrong for most of the world — and genuinely ambiguous everywhere, since 03/04 is two different days depending on the reader.
Explicit patterns are right for a fixed file format, a legacy interface, or somewhere the exact layout is specified. Everywhere else, a locale-aware formatter produces better output with less code.
