Date format tokens
Date formatting tokens across strftime, Day.js/Moment and Excel side by side, plus the traps where the same letters mean different things.
Last updated
strftime (Python/C/Ruby)
| Token | Meaning |
|---|---|
| %Y | 4-digit year, e.g. 2026. |
| %m | 2-digit month, 01 to 12. |
| %d | 2-digit day of month, 01 to 31. |
| %H | 2-digit hour, 24-hour clock, 00 to 23. |
| %M | 2-digit minute, 00 to 59. |
| %S | 2-digit second, 00 to 59. |
| %b | Abbreviated month name, e.g. Sep. |
| %B | Full month name, e.g. September. |
| %a | Abbreviated weekday name, e.g. Fri. |
| %A | Full weekday name, e.g. Friday. |
| %j | Day of the year, 001 to 366. |
| %U | Week number of the year, Sunday as the first day. |
| %s | Unix timestamp — seconds since 1970-01-01 UTC. |
| %z | UTC offset, e.g. +0000 or -0500. |
Day.js / Moment
| Token | Meaning |
|---|---|
| YYYY | 4-digit year, e.g. 2026. |
| MM | 2-digit month, 01 to 12. |
| DD | 2-digit day of month, 01 to 31. |
| HH | 2-digit hour, 24-hour clock, 00 to 23. |
| mm | 2-digit minute, 00 to 59. |
| ss | 2-digit second, 00 to 59. |
| ddd | Abbreviated weekday name, e.g. Fri. |
| dddd | Full weekday name, e.g. Friday. |
| A | AM or PM, uppercase. |
| Z | UTC offset with a colon, e.g. +00:00. |
Excel / Sheets formats
| Token | Meaning |
|---|---|
| yyyy | 4-digit year, e.g. 2026. |
| mm | 2-digit month when next to yyyy or dd; 2-digit minute when next to hh. |
| dd | 2-digit day of month, 01 to 31. |
| hh | 2-digit hour, 24-hour clock by default — add an AM/PM token to switch it to 12-hour. |
| AM/PM | Add this to a time format to switch the hour to 12-hour and show AM or PM. |
| Custom format box | Format Cells > Custom lets you combine any of these tokens in your own pattern. |
The traps
| Token | Meaning |
|---|---|
| MM vs mm | In JS date libraries, MM is month and mm is minute; in Excel it's the reverse — mm can mean either month or minute depending on context. |
| YYYY vs yyyy | Case matters in code (YYYY is year, yyyy would be invalid in Moment/Day.js); Excel isn't case-sensitive at all, so yyyy and YYYY behave identically there. |
| hh vs HH | In Day.js/Moment, hh is 12-hour and HH is 24-hour. Excel has no such split — its format codes are case-insensitive, so hh and HH are identical there and both mean 24-hour until you add AM/PM. |
| %x | Locale-dependent short date — the same format string prints different orders (MM/DD vs DD/MM) depending on the system locale. |
Worth remembering
- →When two ecosystems reuse the same letters for different fields, code is the one place case is load-bearing — Excel format codes are case-insensitive, JS date libraries are not.
- →When in doubt, print a known date through the format and eyeball it — token tables (including this one) are a starting point, not a substitute for checking output.
Questions
Why is my month showing as minutes?
Because mm means minutes in Excel's time context and months elsewhere. Excel decides by what surrounds it, which is why mm/dd/yyyy works and hh:mm gives minutes — the same two characters mean different things.
Why does YYYY sometimes give the wrong year?
You may have used the ISO week-year token instead. In several libraries, uppercase YYYY is the week-based year and differs from the calendar year in the days around New Year — a bug that appears for one week annually.
Which format should I store dates in?
ISO 8601 with an explicit offset. It sorts correctly as text, is unambiguous everywhere, and converts to any display format — whereas a local format cannot be recovered once written.
Is 24-hour or 12-hour the default?
It depends on the token, not the library. In Excel, hh is 24-hour unless AM/PM appears in the same format string, at which point it switches — which surprises people whose times are silently twelve hours out.
Why do the same tokens differ between languages?
Because strftime, Java, .NET and the JavaScript date libraries each evolved separately. There is no shared standard, so a format string carried between two of them is usually wrong rather than portable.