Also available in: Español · Português · Français · العربية
strftime format codes: what each one produces, and who defines it
Type a format string, see the result token by token, and find out which of your tokens will not survive a change of platform.
What strftime format codes are
strftime is the C library function that turns a date into text, and its format string is a run of ordinary characters with conversion specifications mixed in. Each one is a percent sign followed by a letter: %Y is the four-digit year, %m the zero-padded month, %d the day. Everything that is not a conversion is copied through untouched, which is why %Y-%m-%d gives you a hyphenated date without you having to say so.
The same format language turns up far beyond C. Python, Ruby, PHP, R, Perl, awk, GNU date and the shell all take strftime strings, and most of them pass yours straight to the platform's own C library rather than implementing it themselves. That is the whole reason portability is a live question rather than a footnote: the codes your program accepts are decided by the machine it runs on.
There are 42 conversions in all, and they do not come from one place. Some are in the 1989 C standard, one arrived with C99, twelve come from the Single UNIX Specification, six from Olson's timezone package — the same project that gives you the timezone database — and one from glibc itself. Every published cheat sheet flattens that into a single list, which is exactly the information you need when a format string works on your laptop and not in production.
How to use it
- Type or pick a format string. The sample buttons cover an everyday date, a fully portable one, an Apache log line, the ISO week date, and one built from the two genuine collisions in the syntax.
- Set the date and time. Both are read as UTC, so the result depends only on what you typed. The reference table at the bottom re-renders for whatever instant you choose, which is usually faster than reading a description.
- Read the token breakdown and the notes. Each conversion is listed with the standard that defines it and what it produced. The notes underneath cover anything worth knowing — a flag that is not POSIX, a conversion beyond C89, or output that changes with the locale.
Where portability actually breaks, measured
The obvious guess is that the tier boundary is the danger line — stick to C89 and you are safe, stray into the Single UNIX Specification and you are not. Measured on two implementations, that boundary barely bites. Windows CPython 3.12 accepts all 22 C89 conversions and all 12 from the Single UNIX Specification, %e and %F and %T included. A page built around the tier markings would be describing a cliff that has largely eroded.
What breaks is the flags, which are a separate mechanism the tier markings say nothing about. POSIX defines exactly two flag characters, the zero and the plus sign, plus a minimum field width — and then states that the results are unspecified if a flag character is specified without a minimum field width, or a width without a flag. So even %0d is outside the standard: POSIX wants the pair, %03d. glibc instead defines five flags — underscore, hyphen, zero, caret and hash — and accepts every one of them bare.
That is why the single most recommended strftime trick on the internet is the one that breaks. %-d, to drop a leading zero, is a glibc extension in a form POSIX calls unspecified, and on Windows CPython it does not degrade quietly: it raises ValueError. Same for %_d, %s, %P, %k and %l, all of which GNU answers without complaint.
The failure modes are asymmetric, and that is the part worth carrying away. Windows errors loudly on %-d, which is annoying but self-correcting. The workaround someone then reaches for, %#d, is Microsoft's spelling for strip-the-leading-zero — and glibc gives the same character a completely different meaning. In glibc, hash is opposite case, which does nothing at all to a numeric field, so %#d comes back as 07 rather than 7. The flag is not being ignored: %#A really does return SATURDAY, which is how you can tell it is being processed. One character, two definitions, and no error on either side.
Two collisions in the syntax, and one honest limitation
The plus sign is both a POSIX flag character and a conversion the man page lists, in the same position. So %+4Y is a flag with a width, while %+ on its own is a conversion meaning the date in date(1) format. The man page settles the second one in an unusual way: it lists the conversion and then says it is not supported in glibc2. Confirmed — GNU date echoes the two characters back unchanged, which is what this page does too.
The other collision is %G against %Y. %G is the ISO 8601 week-based year, and it disagrees with the calendar year for a handful of days around New Year. 1 January 2027 is a Friday, so it belongs to ISO week 53 of 2026: %G-W%V gives 2026-W53, while %Y-W%V gives 2027-W53 — a week that does not exist, because 2027 has only 52. Swept across the forty years from 2000 to 2039, the two disagree on 68 days out of 14,610, which is 0.47 per cent: never more than three days in any one year, under two on average, and in some years not at all. That is the worst possible frequency for noticing a bug.
The honest limitation is the locale. Eleven of the 42 conversions produce text that the C library draws from the current locale — the weekday and month names, the AM and PM markers, and the three that render a whole date or time in the local convention. This page renders those with the language of the page you are reading, which is a reasonable answer and is not the same answer your server will give. Nothing here can tell you how a machine with a different locale configured will render %c, and a tool claiming otherwise would be guessing.
Two smaller things. Everything is formatted as UTC, so %z is always +0000 and %Z is always UTC; a real program formats in whatever zone it was handed. And %s, the seconds since the epoch, is in the timezone package rather than any C standard, which is why it is one of the conversions Windows refuses outright.
Why is it free?
Turning a date into text is arithmetic and a lookup table, and both run in your browser. There is no server in the loop, so there is nothing to bill for and no account to create.
Nothing is uploaded. Reload the page and it has forgotten your format string.