Skip to content

Date format tokens

There are two widely used families of date format strings and they overlap just enough to be dangerous. strftime — from C, and inherited by Python, Ruby, PHP and GNU date — uses percent tokens like %Y. Unicode LDML, used by ICU, Java, moment and dayjs, uses repeated letters like yyyy. In LDML, MM is a month and mm is a minute; getting that pair backwards is the classic bug.

Every row below is rendered for the same instant: Monday 9 March 2026, 14:05:07 UTC. That date is chosen so nothing hides — a single-digit day and month expose zero-padding, the afternoon hour makes the 12- and 24-hour clocks differ visibly, and the weekday is unambiguous.

An empty equivalent column means the other dialect has no single token for it and you have to compose the value yourself. The test suite renders the calendar fields with the platform's own date functions and compares them to this table, so the examples cannot drift from reality.

Year

4
strftimeLDMLFieldRenders as
%YyyyyFour-digit year2026
%yyyTwo-digit yearAmbiguous by construction. Avoid it in anything stored.26
%CCentury — the year divided by 10020
%GYYYYISO week-numbering yearDiffers from the calendar year around New Year. Use with the ISO week number only.2026

Month

4

In LDML, MM is the month and mm is the minute.

strftimeLDMLFieldRenders as
%mMMMonth, zero-padded03
%-mMMonth, no padding3
%bMMMAbbreviated month nameMar
%BMMMMFull month nameMarch

Day and weekday

8

In LDML, dd is day of month and DDD is day of year.

strftimeLDMLFieldRenders as
%dddDay of month, zero-padded09
%-ddDay of month, no padding9
%eDay of month, space-padded 9
%jDDDDay of year, 001–366068
%aEEEAbbreviated weekday nameMon
%AEEEEFull weekday nameMonday
%uWeekday as a number, Monday is 1%w numbers the same days from Sunday as 0.1
%VwwISO week number, weeks starting Monday11

Time

8
strftimeLDMLFieldRenders as
%HHHHour on the 24-hour clock14
%-HHHour, no padding14
%IhhHour on the 12-hour clock02
%MmmMinute05
%SssSecond07
%3NSSSMilliseconds000
%paAM or PMPM
%sUnix timestamp — seconds since 1970-01-01 UTC1773065107

Time zone

3

An offset is a number; a zone name is a rule. Only the name survives a DST change.

strftimeLDMLFieldRenders as
%zZZUTC offset, no colon+0000
%:zXXXUTC offset with a colon, as ISO 8601 wants it+00:00
%ZzzzTime zone abbreviationAbbreviations are not unique — CST is at least three different zones.UTC

Common combinations

7

Built out of the tokens above — no library needed.

strftimeLDMLFieldRenders as
%Fyyyy-MM-ddISO date2026-03-09
%THH:mm:ss24-hour time14:05:07
%FT%T%:zyyyy-MM-dd'T'HH:mm:ssXXXFull ISO 8601 timestampThe format to store. Sorts as text, unambiguous about the offset.2026-03-09T14:05:07+00:00
%a, %d %b %Y %T %zEEE, dd MMM yyyy HH:mm:ss ZZRFC 2822 — email headers and older HTTPMon, 09 Mar 2026 14:05:07 +0000
%m/%d/%YMM/dd/yyyyUS convention, month first03/09/2026
%d.%m.%Ydd.MM.yyyyEuropean convention, day first09.03.2026
%%''A literal percent sign%

FAQ

What is the difference between yyyy and YYYY?
In LDML, yyyy is the calendar year and YYYY is the ISO week-numbering year. They differ for a few days each January: 2027-01-01 falls in ISO week 53 of 2026, so YYYY reads 2026 there. Using YYYY by accident produces a bug that appears once a year and then disappears, which is why it is so hard to catch.
Why is my month showing up as minutes?
Because you are in an LDML dialect and used mm instead of MM. LDML is case-sensitive: M is month, m is minute, D is day of year, d is day of month. strftime has the same trap in a different place — %M is minutes and %m is the month.
How do I get a padded versus unpadded number?
In strftime, the GNU extension %-d strips the padding, so %d is 09 and %-d is 9. In LDML the letter count sets the width directly: d is 9 and dd is 09. Neither is portable — %-d does not exist on every platform.
Which format should I store dates in?
ISO 8601 with an explicit offset — 2026-03-09T14:05:07+00:00. It sorts correctly as text, it is unambiguous about the offset, and every language parses it. Store that and format for display at the last possible moment; a stored local date without an offset is unrecoverable information loss.